/home/pi/programowanie/iDom_server_OOP/libs/Statistic/statistic_test/../statistic.h
1
#ifndef STATISTIC_H
2
#define STATISTIC_H
3
#include <iostream>
4
#include <deque>
5
#include <numeric>
6
#include <algorithm>
7
#include <sstream>
8
#include <cmath>
9
#include <vector>
10
11
template <class T>
12
class STATISTIC
13
{
14
public:
15
    STATISTIC(unsigned int size): m_size(size)
2.21k
16
    {
2.21k
17
2.21k
18
    }
12
19
    void resize(unsigned int i){
12
20
        if (i < m_size){
96
21
            while(m_dequeue.size()> i){
84
22
                pop_front();
84
23
            }
12
24
        }
12
25
        m_size = i;
12
26
    }
316
27
    T size(){
316
28
        return  static_cast<T>(m_dequeue.size());
316
29
    }
40
30
    void push_front(T v){
40
31
        if (m_dequeue.size() >= m_size){
4
32
            pop_back();
4
33
        }
40
34
        m_dequeue.push_front(v);
40
35
    }
1.22k
36
    void push_back(T v){
1.22k
37
        if (m_dequeue.size() >= m_size){
8
38
            pop_front();
8
39
        }
1.22k
40
        m_dequeue.push_back(v);
1.22k
41
    }
12
42
    void pop_back(){
12
43
        m_dequeue.pop_back();
12
44
        // std::cout <<"pop_back"<<std::endl;
12
45
    }
92
46
    void pop_front(){
92
47
        m_dequeue.pop_front();
92
48
        // std::cout <<"pop_front"<<std::endl;
92
49
    }
50
    ///////////////////////////////////////////// statistic /////////////////////////////
20
51
    T median(){
20
52
        auto backup = m_dequeue;
20
53
        std::sort(backup.begin(), backup.end());
20
54
        if (backup.size() % 2 != 0){
12
55
            return backup[backup.size() / 2];
12
56
        }
8
57
        else{
8
58
            T m = backup[backup.size() / 2] + backup[(backup.size() / 2)-1];
8
59
            return m /2;
8
60
        }
20
61
    }
92
62
    T sum(){
92
63
        return std::accumulate(m_dequeue.begin(), m_dequeue.end(), static_cast<T>(0));
92
64
    }
65
92
66
    T average(){
92
67
        T av  = sum() /size();
92
68
        return av;
92
69
    }
70
20
71
    T max(){
20
72
        T max = m_dequeue[0];
160
73
        for (auto v : m_dequeue){
160
74
            if (v > max){
52
75
                max = v;
52
76
            }
160
77
        }
20
78
        return max;
20
79
    }
80
20
81
    T min(){
20
82
        T min = m_dequeue[0];
160
83
        for (auto v : m_dequeue){
160
84
            if (v < min){
12
85
                min = v;
12
86
            }
160
87
        }
20
88
        return min;
20
89
    }
90
4
91
    T range(){
4
92
        return max() - min();
4
93
    }
94
24
95
    T standardDeviation(){
24
96
        double standardDeviation = 0.0;
24
97
        T _av = average();
24
98
152
99
        for(int i = 0; i < size(); ++i){
128
100
            standardDeviation += pow(m_dequeue.at(i) - _av, 2);
128
101
        }
24
102
        return sqrt(standardDeviation / size());
24
103
    }
104
12
105
    T coefficientOfVariation(){
12
106
12
107
        return (standardDeviation()/average()) /** 100*/;
12
108
    }
109
52
110
    T mode(){
52
111
52
112
        T _mode = 0;
52
113
        T _modeTemp = 0;
52
114
        int counter = 1;
52
115
        int modeCounter = 1;
52
116
        auto backup = m_dequeue;
52
117
        if(m_dequeue.size() == 1)
12
118
        {
12
119
            return m_dequeue.at(0);
12
120
        }
40
121
        std::sort(backup.begin(), backup.end());
40
122
#ifdef BT_TEST
40
123
        std::cout << " " << std::endl;
40
124
        for (auto i : backup)
356
125
        {
356
126
            std::cout << i << " ";
356
127
        }
40
128
        std::cout << " " << std::endl;
40
129
#endif
40
130
        _mode = _modeTemp = backup.at(0);
40
131
        backup.pop_front();
40
132
        for (auto b : backup)
316
133
        {
316
134
            if (_modeTemp == b)
60
135
            {
60
136
                modeCounter++;
60
137
            }
316
138
            else
256
139
            {
256
140
                _modeTemp = b;
256
141
                modeCounter = 1;
256
142
            }
316
143
316
144
            if(counter < modeCounter)
32
145
            {
32
146
                counter = modeCounter;
32
147
                _mode = _modeTemp;
32
148
            }
316
149
        }
40
150
#ifdef BT_TEST
40
151
        std::cout << " moda: " << _mode << " wystepuje razy " << counter << std::endl;
40
152
#endif
40
153
        return _mode;
52
154
    }
155
156
    float trend(){
157
        int down = 0;
158
        int eq = 0;
159
        int up = 0;
160
        int lp = 0;
161
        T diff = 0;
162
        T first = m_dequeue[0];
163
164
        for (auto i = 1; i < m_dequeue.size(); ++i){
165
            if (first < m_dequeue[i]){
166
                up++;
167
                if (m_dequeue[i] - first > diff){
168
                    diff = m_dequeue[i] - first;
169
                    lp = i;
170
                }
171
            }
172
            if (first == m_dequeue[i]){ eq++;}
173
            if (first > m_dequeue[i]){
174
                if (diff < first - m_dequeue[i] ){
175
                    diff = first - m_dequeue[i];
176
                    lp = i;
177
                }
178
                down++;
179
            }
180
            first = m_dequeue[i];
181
        }
182
        std::cout <<"up "<<up<<" eq "<< eq << " down "<< down <<" max diff "<< diff<<" lp "<<lp << std::endl;
183
        return 2.2;
184
    }
185
80
186
    bool isMoreDiff(T diff){
80
187
        if (m_dequeue.size()>2){
56
188
            T d = m_dequeue.at( m_dequeue.size()-2)
56
189
                    - m_dequeue.at( m_dequeue.size() - 1);
56
190
            d = fabs(d);
56
191
            if (d > diff && m_alarm == false){
24
192
                m_alarm = true;
24
193
                return true;
24
194
            }
32
195
            if (d <= diff){
32
196
                m_alarm = false;
32
197
                return false;
32
198
            }
32
199
        }
24
200
        return false;
80
201
    }
28
202
    std::pair<double,double> getLast2(){
28
203
        if (m_dequeue.size()>2){
24
204
            return std::make_pair(static_cast<double>(m_dequeue.at( m_dequeue.size()-2)),
24
205
                                  static_cast<double>(m_dequeue.at( m_dequeue.size()-1))    );
24
206
        }
28
207
#ifdef BT_TEST
4
208
        puts("no data - return 0.0 0.0");
4
209
#endif
4
210
        return std::make_pair(0.0,0.0);
28
211
    }
212
213
    /////////////////////////////////////////////////////////////////////////////////////
56
214
    void print(){
284
215
        for(auto n : m_dequeue){
284
216
            std::cout << ","<< n;
284
217
        }
56
218
        std::cout << " " <<std::endl;
56
219
    }
220
221
16
222
    std::string stats(){
16
223
16
224
        std::stringstream ss(" brak danych =(");
16
225
        if(size()>0)
12
226
        {
12
227
            ss.str("");
12
228
            ss <<"rozmiar tablicy: "<< size() <<std::endl
12
229
              << "min: "<< min() <<std::endl
12
230
              << "max: "<< max()<<std::endl
12
231
              << "srednia " << average() <<std::endl
12
232
              << "mediana " << median()  <<std::endl
12
233
              << "odchylenie st "<< standardDeviation() << std::endl
12
234
              << "wspolczynnik zmiennosci " << coefficientOfVariation() <<"%"<< std::endl
12
235
              << "Dominanta " << mode();
12
236
12
237
12
238
            ss << std::endl
12
239
               << "data " <<  std::endl;
64
240
            for(auto n : m_dequeue){
64
241
                ss << "|"<< n;
64
242
            }
12
243
        }
16
244
        ss <<  std::endl;
16
245
        return ss.str();
16
246
    }
247
248
private:
249
    unsigned int m_size;
250
    std::deque <T> m_dequeue;
251
    bool m_alarm = false;
252
};
253
254
#endif // STATISTIC_H
/home/pi/programowanie/iDom_server_OOP/libs/Statistic/statistic_test/statistic_BT.cpp
1
#include <gtest/gtest.h>
2
#include <gmock/gmock.h>
3
#include "../statistic.h"
4
5
class StatisticClass_fixture : public ::testing::Test
6
{
7
public:
8
    STATISTIC<double> average;
9
    StatisticClass_fixture(): average(12)
28
10
    {
28
11
    }
12
    void SetUp() final
28
13
    {
28
14
        average.push_back(1);
28
15
        average.push_back(1);
28
16
        average.push_back(2);
28
17
        average.push_back(2);
28
18
        average.push_back(3);
28
19
        average.push_back(3);
28
20
        average.push_back(4);
28
21
        average.push_back(4);
28
22
        average.push_back(-5);
28
23
        average.push_back(-5);
28
24
        average.push_back(6);
28
25
        average.push_back(6);
28
26
    }
27
    void TearDown() final
28
28
    {
28
29
28
30
    }
31
};
32
33
TEST_F(StatisticClass_fixture, range)
4
34
{
4
35
    EXPECT_DOUBLE_EQ(average.average() , 1.8333333333333333);
4
36
    EXPECT_EQ(average.range(), 11);
4
37
}
38
39
TEST_F(StatisticClass_fixture, average)
4
40
{
4
41
    EXPECT_DOUBLE_EQ(average.average() , 1.8333333333333333);
4
42
    std::string ret = average.stats();
4
43
    EXPECT_THAT(ret, testing::HasSubstr("max"));
4
44
}
45
TEST_F(StatisticClass_fixture, averageOne)
4
46
{
4
47
    average.resize(1);
4
48
    average.push_back(1);
4
49
    EXPECT_DOUBLE_EQ(average.average() , 1.0);
4
50
}
51
TEST_F(StatisticClass_fixture, median)
4
52
{
4
53
    EXPECT_EQ(average.median(),2.5f);
4
54
}
55
TEST(StatisticClass, medianOne)
4
56
{
4
57
    STATISTIC<double> average(1);
4
58
    average.push_back(1);
4
59
    EXPECT_EQ(average.median(), 1.0f);
4
60
}
61
TEST_F(StatisticClass_fixture, min)
4
62
{
4
63
    EXPECT_EQ(average.min(),-5.0f);
4
64
}
65
TEST_F(StatisticClass_fixture, max)
4
66
{
4
67
    EXPECT_EQ(average.max(),6);
4
68
}
69
TEST_F(StatisticClass_fixture, push_and_pop)
4
70
{
4
71
    average.pop_back();
4
72
    EXPECT_EQ(average.size(),11);
4
73
    average.push_front(3.9);
4
74
    EXPECT_EQ(average.size(),12);
4
75
    average.pop_back();
4
76
    EXPECT_EQ(average.size(),11);
4
77
}
78
79
TEST(StatisticClass, resize)
4
80
{
4
81
    unsigned int s = 3;
4
82
    STATISTIC<double> average(12);
4
83
    average.push_back(1);
4
84
    average.push_back(2);
4
85
    average.push_back(3);
4
86
    average.push_back(4);
4
87
    average.push_back(5);
4
88
    average.push_front(44);
4
89
    average.push_front(45);
4
90
    average.print();
4
91
    average.resize(s);
4
92
4
93
    EXPECT_EQ(average.size(),static_cast<double>(s));
4
94
4
95
    auto data = average.getLast2();
4
96
    average.print();
4
97
4
98
    EXPECT_EQ(data.first,4.0);
4
99
    EXPECT_EQ(data.second,5.0);
4
100
}
101
102
TEST(StatisticClass, getLast2_empty)
4
103
{
4
104
    unsigned int s = 1;
4
105
    STATISTIC<double> average(12);
4
106
    average.push_back(1);
4
107
    average.push_back(2);
4
108
    average.push_back(3);
4
109
    average.push_back(4);
4
110
    average.push_back(5);
4
111
    average.push_front(44);
4
112
    average.push_front(45);
4
113
    average.print();
4
114
    average.resize(s);
4
115
    average.push_front(33);
4
116
4
117
    EXPECT_EQ(average.size(),static_cast<double>(s));
4
118
4
119
    auto data = average.getLast2();
4
120
    average.print();
4
121
4
122
    EXPECT_EQ(data.first,0.0);
4
123
    EXPECT_EQ(data.second,0.0);
4
124
}
125
126
TEST(StatisticClass, moreDiff)
4
127
{
4
128
    STATISTIC<double> average(12);
4
129
    average.push_back(1);
4
130
    average.push_back(2);
4
131
    average.push_back(30);
4
132
    average.push_back(4);
4
133
    average.push_back(5);
4
134
    average.push_front(44);
4
135
    average.push_front(45);
4
136
    average.print();
4
137
4
138
    EXPECT_FALSE(average.isMoreDiff(2.2));
4
139
4
140
    average.push_back(7.3);
4
141
    average.print();
4
142
4
143
    EXPECT_TRUE(average.isMoreDiff(2.2));
4
144
}
145
146
TEST(StatisticClass, moreDiff_wrong)
4
147
{
4
148
    STATISTIC<double> average(1);
4
149
    average.push_back(1);
4
150
4
151
    average.print();
4
152
4
153
    EXPECT_FALSE(average.isMoreDiff(2.2));
4
154
4
155
    average.push_back(7.3);
4
156
    average.print();
4
157
4
158
    EXPECT_FALSE(average.isMoreDiff(2.2));
4
159
}
160
161
TEST(StatisticClass, noMoreDiff)
4
162
{
4
163
    STATISTIC<double> average(12);
4
164
    average.push_back(1);
4
165
    average.push_back(2);
4
166
    average.push_back(30);
4
167
    average.push_back(4);
4
168
    average.push_back(5);
4
169
    average.push_front(44);
4
170
    average.push_front(45);
4
171
    average.print();
4
172
4
173
    EXPECT_FALSE(average.isMoreDiff(6.2));
4
174
4
175
    average.push_back(7.3);
4
176
    average.print();
4
177
4
178
    EXPECT_FALSE(average.isMoreDiff(9.2));
4
179
}
180
181
TEST(StatisticClass, mode)
4
182
{
4
183
    STATISTIC<double> average(22);
4
184
    average.push_back(29.62);
4
185
    average.push_back(29.71);
4
186
    average.push_back(30.19);
4
187
    average.push_back(33.5);
4
188
    average.push_back(30.31);
4
189
    average.push_back(30.81);
4
190
    average.push_back(30.87);
4
191
    average.push_back(31.25);
4
192
    average.push_back(31.31);
4
193
    average.push_back(31.56);
4
194
    average.push_back(31.87);
4
195
    average.push_back(31.94);
4
196
    average.push_back(32.13);
4
197
    average.push_back(32.13);  //to
4
198
    average.push_back(32.63);
4
199
4
200
    average.print();
4
201
    std::cout << "1 MODE: " << average.mode() << std::endl;
12
202
    EXPECT_DOUBLE_EQ(32.13,average.mode()) << "ZLA DOMINANTA 32.13";
4
203
    average.push_back(33.5);
4
204
    average.push_back(33.5);
4
205
    std::cout << "2 MODE: " << average.mode() << std::endl;
12
206
    EXPECT_DOUBLE_EQ(33.5,average.mode()) << "ZLA DOMINANTA 33.5";
4
207
}
208
TEST(StatisticClass, modeOne)
4
209
{
4
210
    STATISTIC<double> average(1);
4
211
    average.push_back(29.62);
4
212
    average.print();
4
213
    std::cout << "1 MODE: " << average.mode() << std::endl;
12
214
    EXPECT_DOUBLE_EQ(29.62,average.mode()) << "ZLA DOMINANTA 32.13";
4
215
}
216
TEST(StatisticClass, modeTwo)
4
217
{
4
218
    STATISTIC<double> average(10);
4
219
    average.push_back(29.62);
4
220
    average.push_back(28.62);
4
221
    average.print();
4
222
    std::cout << "1 MODE: " << average.mode() << std::endl;
12
223
    EXPECT_DOUBLE_EQ(28.62,average.mode()) << "ZLA DOMINANTA 32.13";
4
224
}
225
TEST(StatisticClass, modeThree)
4
226
{
4
227
    STATISTIC<double> average(10);
4
228
    average.push_back(29.62);
4
229
    average.push_back(28.62);
4
230
    average.push_back(29.63);
4
231
    average.print();
4
232
    std::cout << "1 MODE: " << average.mode() << std::endl;
12
233
    EXPECT_DOUBLE_EQ(28.62,average.mode()) << "ZLA DOMINANTA 32.13";
4
234
}
/home/pi/programowanie/iDom_server_OOP/libs/emoji/emoji.cpp
1
#include <sstream>
2
#include "emoji.h"
3
4
EMOJI::EMOJI()
0
5
{
0
6
0
7
}
8
9
std::string EMOJI::emoji(E_emoji e)
96
10
{
0
11
    switch (e) {
56
12
    case E_emoji::NORTH_EAST_ARROW:
56
13
        return HEX_STR::hexToStr("E28697");
12
14
    case E_emoji::SOUTH_EAST_ARROW:
12
15
        return HEX_STR::hexToStr("E28698");
0
16
    case E_emoji::NORTH_WEST_ARROW:
0
17
        return HEX_STR::hexToStr("E28696");
0
18
    case E_emoji::SOUTH_WEST_ARROW:
0
19
        return HEX_STR::hexToStr("E28699");
0
20
    case E_emoji::LEFT_RIGHT_ARROW:
0
21
        return HEX_STR::hexToStr("E28694");
0
22
    case E_emoji::UP_DOWN_ARROW:
0
23
        return HEX_STR::hexToStr("E28695");
0
24
    case E_emoji::ALARM_CLOCK:
0
25
        return HEX_STR::hexToStr("E28FB0");
0
26
    case E_emoji::SUN_WITH_FACE:
0
27
        return HEX_STR::hexToStr("F09F8C9E");
0
28
    case E_emoji::SNOWFLAKE:
0
29
        return HEX_STR::hexToStr("E29D84");
0
30
    case E_emoji::HEAVY_BLACK_HEART:
0
31
        return HEX_STR::hexToStr("E29DA4");
4
32
    case E_emoji::WARNING_SIGN:
4
33
        return HEX_STR::hexToStr("E29AA0");
8
34
    case E_emoji::CHART_WITH_DOWNWARDS_TREND:
8
35
        return HEX_STR::hexToStr("F09F9389");
8
36
    case E_emoji::CHART_WITH_UPWARDS_TREND:
8
37
        return HEX_STR::hexToStr("F09F9388");
8
38
    case E_emoji::THUNDER_CLOUD_AND_RAIN:
8
39
        return HEX_STR::hexToStr("E29B88");
0
40
0
41
    }
96
42
    return"ok";
96
43
}
44
45
std::string HEX_STR::hexToStr(const std::string& hex)
96
46
{
96
47
    std::string res;
96
48
    res.reserve(hex.size() / 2);
400
49
    for (unsigned int i = 0; i < hex.size(); i += 2)
304
50
    {
304
51
        std::istringstream iss(hex.substr(i, 2));
304
52
        int temp;
304
53
        iss >> std::hex >> temp;
304
54
        res += static_cast<char>(temp);
304
55
    }
96
56
    return res;
96
57
}
/home/pi/programowanie/iDom_server_OOP/libs/event_counters/event/event_command.cpp
1
#include "event_command.h"
2
3
event_command::event_command(const std::string& name):  event_counters(name)
584
4
{
584
5
584
6
}
7
8
std::string event_command::help()
8
9
{
8
10
    return "event command";
8
11
}
/home/pi/programowanie/iDom_server_OOP/libs/event_counters/event/event_mpd.cpp
1
#include "event_mpd.h"
2
3
event_mpd::event_mpd(const std::string& name): event_counters(name)
584
4
{
584
5
584
6
}
7
8
std::string event_mpd::help()
4
9
{
4
10
    return "event from MPD";
4
11
}
/home/pi/programowanie/iDom_server_OOP/libs/event_counters/event/event_pilot.cpp
1
#include "event_pilot.h"
2
3
event_pilot::event_pilot(const std::string& name): event_counters(name)
584
4
{
584
5
584
6
}
7
8
std::string event_pilot::help()
4
9
{
4
10
    return "pilot events";
4
11
}
/home/pi/programowanie/iDom_server_OOP/libs/event_counters/event/event_unknown.cpp
1
#include "event_unknown.h"
2
3
event_unknown::event_unknown(const std::string& name) : event_counters(name), name(name)
780
4
{
780
5
780
6
}
7
8
std::string event_unknown::help()
148
9
{
148
10
    return  name+" event";
148
11
}
/home/pi/programowanie/iDom_server_OOP/libs/event_counters/event/new_connect_event.cpp
1
#include "new_connect_event.h"
2
#include <iostream>
3
new_Connect_Event::new_Connect_Event(const std::string& name) : event_counters(name)
584
4
{
584
5
584
6
}
7
8
new_Connect_Event::~new_Connect_Event()
584
9
{
584
10
    std::cout << " kasujemy obiekt" << std::endl;
584
11
}
12
13
std::string new_Connect_Event::help()
8
14
{
8
15
    return "connection start event";
8
16
}
17
18
19
20
21
22
/home/pi/programowanie/iDom_server_OOP/libs/event_counters/event_counters.cpp
1
#include "event_counters.h"
2
#include <iostream>
3
#include <iomanip>
4
#include <ctime>
5
#include <sstream>
6
#include <string>
7
#include <algorithm>
8
9
event_counters::event_counters(std::string name) : eventName(std::move(name))
3.11k
10
{
3.11k
11
3.11k
12
}
13
14
int event_counters::howManyEvent()
144
15
{
144
16
    std::lock_guard < std::mutex > lock ( eventMutex);
144
17
    return static_cast<int>( eventList.size() );
144
18
}
19
20
void event_counters::addEvent(const std::string& note)
20.4k
21
{
20.4k
22
    eventStruct d;
20.4k
23
    std::ostringstream oss;
20.4k
24
20.4k
25
    auto t = std::time(nullptr);
20.4k
26
    auto tm = *std::localtime(&t);
20.4k
27
    oss << std::put_time(&tm, "%d-%m-%Y %H:%M:%S");
20.4k
28
20.4k
29
    d.date = oss.str();
20.4k
30
    d.note = note;
20.4k
31
    d.posixTime = static_cast<unsigned int> (std::time(nullptr));
20.4k
32
    std::lock_guard < std::mutex > lock ( eventMutex);
20.4k
33
    eventList.push_back(d);
20.4k
34
}
35
36
std::string event_counters::getEvent()
144
37
{
144
38
    std::stringstream ret;
144
39
    ret << "Event: " << help() << "\n";
144
40
    std::lock_guard <std::mutex> lock(eventMutex);
144
41
    int k =0;
33.1k
42
    for (auto i : eventList){
33.1k
43
        ret << ++k << "\t" << i.date << "     " <<  i.note << "\n";
33.1k
44
    }
144
45
    ret << "\n event per last minute: " << getLast1minNumberEvent_NO_Mutex() << "\n------------------------------";
144
46
    return ret.str();
144
47
}
48
49
void event_counters::clearEvent()
8
50
{
8
51
    std::lock_guard <std::mutex> lock(eventMutex);
8
52
    eventList.clear();
8
53
}
54
55
void event_counters::clearEvent(unsigned int from, unsigned int to)
16
56
{
16
57
    if (to < from){
4
58
        return;
4
59
    }
12
60
    auto max = static_cast<unsigned int>( eventList.size() );
12
61
12
62
    if (max < to){
8
63
        to = max;
8
64
    }
12
65
    if(max<from){
4
66
        from = max;
4
67
        to = max;
4
68
    }
12
69
    std::lock_guard <std::mutex> lock(eventMutex);
12
70
    eventList.erase(eventList.begin()+from, eventList.begin()+to);
12
71
}
72
73
unsigned int event_counters::getLast1minNumberEvent()
48
74
{
48
75
    std::lock_guard <std::mutex> lock(eventMutex);
48
76
    return getLast1minNumberEvent_NO_Mutex();
48
77
}
78
79
std::string event_counters::getEventName()
3.11k
80
{
3.11k
81
    return eventName;
3.11k
82
}
83
84
unsigned int event_counters::getLast1minNumberEvent_NO_Mutex()
192
85
{
192
86
    unsigned int k = 0;
192
87
    if (eventList.empty())
8
88
        return k;
184
89
    unsigned int lastPosix = static_cast<unsigned int> (std::time(nullptr));// eventList.at(eventList.size()-1).posixTime;
184
90
35.4k
91
    for (auto i = eventList.size()-1; i != -1; i--)
35.3k
92
    {
35.3k
93
        if(eventList.at(i).posixTime+60 > lastPosix)
35.2k
94
            k++;
35.3k
95
        else
4
96
            break;
35.3k
97
    }
184
98
    return k;
192
99
}
/home/pi/programowanie/iDom_server_OOP/libs/event_counters/event_counters_handler.cpp
1
#include "event_counters_handler.h"
2
#include "event/new_connect_event.h"
3
#include "event/event_unknown.h"
4
#include "event/event_mpd.h"
5
#include "event/event_pilot.h"
6
#include "event/event_command.h"
7
8
9
event_counters_handler::event_counters_handler()
584
10
{
584
11
    std::shared_ptr <event_counters> newConnectEvent (new new_Connect_Event("connections") );
584
12
    eventCountersMap.insert( std::make_pair( newConnectEvent->getEventName(), newConnectEvent ) );
584
13
584
14
    std::shared_ptr <event_counters> newUnknownEvent (new event_unknown("unknown") );
584
15
    eventCountersMap.insert( std::make_pair( newUnknownEvent->getEventName(), newUnknownEvent ) );
584
16
584
17
    std::shared_ptr <event_counters> eventMPD (new event_mpd("mpd") );
584
18
    eventCountersMap.insert( std::make_pair( eventMPD->getEventName(), eventMPD ) );
584
19
584
20
    std::shared_ptr <event_counters> eventPilot (new event_pilot("pilot") );
584
21
    eventCountersMap.insert( std::make_pair( eventPilot->getEventName(), eventPilot ) );
584
22
584
23
    std::shared_ptr <event_counters> eventCommand (new event_command("command") );
584
24
    eventCountersMap.insert( std::make_pair( eventCommand->getEventName(), eventCommand ) );
584
25
}
26
27
std::shared_ptr<event_counters> event_counters_handler::run(const std::string& name)
20.7k
28
{
20.7k
29
20.7k
30
    if (eventCountersMap.find(name) == eventCountersMap.end()){
196
31
        addEvent(name);
196
32
    }
20.7k
33
    return eventCountersMap[name];
20.7k
34
}
35
36
std::string event_counters_handler::getListPossibleEvents()
4
37
{
4
38
    std::string result;
4
39
28
40
    for( auto iter= eventCountersMap.begin();iter != eventCountersMap.end(); ++iter ) {
24
41
        result+= iter->first;
24
42
        result+= "\n";
24
43
    }
4
44
    return result;
4
45
}
46
47
std::string event_counters_handler::help(const std::string& name)
8
48
{
8
49
    std::string result;
8
50
8
51
    if (name.empty()){
28
52
        for( auto iter= eventCountersMap.begin();iter != eventCountersMap.end(); ++iter ) {
24
53
            result+= iter->second->help();
24
54
            result+= "\n------------------------------\n";
24
55
        }
4
56
    }
4
57
    else{
4
58
        result = eventCountersMap[name]->help();
4
59
    }
8
60
8
61
    return result;
8
62
}
63
std::mutex event_counters_handler::echMutex;
64
65
void event_counters_handler::addEvent(const std::string& name)
196
66
{
196
67
    std::lock_guard <std::mutex> lock(event_counters_handler::echMutex);
196
68
    std::shared_ptr <event_counters> newUnknownEvent (new event_unknown(name) );
196
69
    eventCountersMap.insert( std::make_pair( newUnknownEvent->getEventName(), newUnknownEvent ) );
196
70
}
/home/pi/programowanie/iDom_server_OOP/libs/event_counters/test/event_BT.cpp
1
#include <gtest/gtest.h>
2
#include "test_data.h"
3
#include "../../../iDom_server_OOP/src/iDomTools/test/iDomTools_fixture.h"
4
#include "../event_counters_handler.h"
5
6
class event_counter_fixture : public iDomTOOLS_ClassTest
7
{
8
public:
9
     event_counters_handler mainEvent;
10
     std::string msg = "info";
11
     std::string testEvent = "testEvent";
20
12
     void preper1001Event(){
20
13
         int counter = 1000;
20
14
         EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),0);
20
15
         mainEvent.run(testEvent)->addEvent(msg);
20
16
         EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1);
20
17
         std::string returnedString = mainEvent.run(testEvent)->getEvent();
20
18
         EXPECT_THAT(returnedString, testing::HasSubstr(msg));
20
19
         EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1);
20
20
20.0k
21
         for (int i = 1; i!= counter; counter--)
19.9k
22
         {
19.9k
23
             mainEvent.run(testEvent)->addEvent(msg);
19.9k
24
             if(counter == 500)
20
25
                 mainEvent.run(testEvent)->addEvent("cyniu");
19.9k
26
         }
20
27
         EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1001);
20
28
         returnedString = mainEvent.run(testEvent)->getEvent();
20
29
         EXPECT_THAT(returnedString, testing::HasSubstr("cyniu"));
20
30
     }
31
};
32
33
TEST_F(event_counter_fixture, add_get_clear_event)
4
34
{
4
35
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),0);
4
36
    mainEvent.run(testEvent)->addEvent(msg);
4
37
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1);
4
38
    std::string returnedString = mainEvent.run(testEvent)->getEvent();
4
39
    EXPECT_THAT(returnedString, testing::HasSubstr(msg));
4
40
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1);
4
41
    mainEvent.run(testEvent)->clearEvent();
4
42
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),0);
4
43
}
44
45
TEST_F(event_counter_fixture, clear_middle_part_of_event_small_big)
4
46
{
4
47
    preper1001Event();
4
48
    mainEvent.run(testEvent)->clearEvent(400,600);
4
49
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),801);
4
50
    std::string returnedString = mainEvent.run(testEvent)->getEvent();
4
51
    EXPECT_THAT(returnedString, testing::Not(testing::HasSubstr("cyniu")));
4
52
}
53
54
TEST_F(event_counter_fixture, clear_middle_part_of_event_big_small)
4
55
{
4
56
    preper1001Event();
4
57
    mainEvent.run(testEvent)->clearEvent(600,400);
4
58
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1001);
4
59
    std::string returnedString = mainEvent.run(testEvent)->getEvent();
4
60
    EXPECT_THAT(returnedString,testing::HasSubstr("cyniu"));
4
61
}
62
63
TEST_F(event_counter_fixture, clear_middle_part_of_event_to_max)
4
64
{
4
65
    preper1001Event();
4
66
    mainEvent.run(testEvent)->clearEvent(400,1600);
4
67
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),400);
4
68
    std::string returnedString = mainEvent.run(testEvent)->getEvent();
4
69
    EXPECT_THAT(returnedString, testing::Not(testing::HasSubstr("cyniu")));
4
70
}
71
72
TEST_F(event_counter_fixture, clear_middle_part_of_event_from_max)
4
73
{
4
74
    preper1001Event();
4
75
    mainEvent.run(testEvent)->clearEvent(1400,1600);
4
76
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1001);
4
77
    std::string returnedString = mainEvent.run(testEvent)->getEvent();
4
78
    EXPECT_THAT(returnedString, testing::HasSubstr("cyniu") );
4
79
}
80
81
TEST_F(event_counter_fixture, getListPossibleEvents)
4
82
{
4
83
    mainEvent.run("INFO")->addEvent("kokolino");
4
84
   std::string returnedString = mainEvent.getListPossibleEvents();
4
85
   std::cout << "wynik: " << returnedString << std::endl;
4
86
   EXPECT_THAT(returnedString, testing::HasSubstr("INFO") );
4
87
}
88
89
TEST_F(event_counter_fixture, getHelp)
4
90
{
4
91
   mainEvent.run("INFO")->addEvent("kokolino");
4
92
   std::string returnedString = mainEvent.help("connections");
4
93
   std::cout << "wynik: " << returnedString << std::endl;
4
94
   EXPECT_THAT(returnedString, testing::HasSubstr("start") );
4
95
   returnedString = mainEvent.help("");
4
96
   std::cout << "wynik: " << returnedString << std::endl;
4
97
   EXPECT_THAT(returnedString, testing::HasSubstr("pilot") );
4
98
}
99
100
TEST_F(event_counter_fixture, getLast1minNumberEvent)
4
101
{
4
102
    preper1001Event();
4
103
    mainEvent.run(testEvent)->eventList.at(500).posixTime -= 65;
4
104
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1001);
4
105
    EXPECT_EQ(mainEvent.run(testEvent)->getLast1minNumberEvent(),500);
4
106
}
107
TEST_F(event_counter_fixture, getLast1minNumberEventWhenEmpty)
4
108
{
4
109
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),0);
4
110
    EXPECT_EQ(mainEvent.run(testEvent)->getLast1minNumberEvent(),0);
4
111
}
/home/pi/programowanie/iDom_server_OOP/libs/sunrise-sunset/sunriseset.cpp
1
#include "sunriseset.h"
2
3
double SunRiseSet::FNday(int y, int m, int d, float h)
182
4
{
182
5
    long int luku = - 7 * (y + (m + 9)/12)/4 + 275*m/9 + d;
182
6
182
7
    // Typecasting needed for TClite on PC DOS at least, to avoid product overflow
182
8
    luku+= (long int)y*367;
182
9
182
10
    return (double)luku - 730531.5 + h/24.0;
182
11
}
12
double SunRiseSet::FNrange(double x)
546
13
{
546
14
    double b = x / tpi;
546
15
    double a = tpi * (b - (long)(b));
546
16
    if (a < 0) a = tpi + a;
546
17
    return a;
546
18
}
19
20
double SunRiseSet::f0(double lat, double declin)
182
21
{
182
22
    double fo,dfo;
182
23
    // Correction: different sign at S HS
182
24
    dfo = rads*(0.5*SunDia + AirRefr); if (lat < 0.0) dfo = -dfo;
182
25
    fo = tan(declin + dfo) * tan(lat*rads);
182
26
182
27
    if (fo > 0.99999) fo=1.0; // to avoid overflow //
182
28
    fo = asin(fo) + pi/2.0;
182
29
    return fo;
182
30
}
31
32
double SunRiseSet::f1(double lat, double declin)
4
33
{
4
34
    double fi,df1;
4
35
    // Correction: different sign at S HS
4
36
    df1 = rads * 6.0; if (lat < 0.0) df1 = -df1;
4
37
    fi = tan(declin + df1) * tan(lat*rads);
4
38
4
39
    if (fi > 0.99999) fi=1.0; // to avoid overflow //
4
40
    fi = asin(fi) + pi/2.0;
4
41
    return fi;
4
42
}
43
44
double SunRiseSet::FNsun(double d)
182
45
{
182
46
    // mean longitude of the Sun
182
47
    L = FNrange(280.461 * rads + .9856474 * rads * d);
182
48
182
49
    // mean anomaly of the Sun
182
50
    g = FNrange(357.528 * rads + .9856003 * rads * d);
182
51
182
52
    // Ecliptic longitude of the Sun
182
53
    return FNrange(L + 1.915 * rads * sin(g) + .02 * rads * sin(2 * g));
182
54
}
55
56
Clock SunRiseSet::gethrmn(double dhr)
218
57
{
218
58
218
59
    int hr,mn;
218
60
218
61
    hr=(int) dhr;
218
62
    mn = (dhr - (double) hr)*60;
218
63
218
64
    Clock ret(hr,mn);
218
65
218
66
    return ret;
218
67
}
68
69
SunRiseSet::SunRiseSet()
532
70
{
532
71
532
72
}
73
74
std::string SunRiseSet::getAllData()
4
75
{
4
76
    double y,m,day,h,latit,longit;
4
77
4
78
    time_t sekunnit;
4
79
    struct tm *p;
4
80
4
81
    // get the date and time from the user
4
82
    // read system date and extract the year
4
83
4
84
    /** First get current time **/
4
85
    time(&sekunnit);
4
86
4
87
    /** Next get localtime **/
4
88
4
89
    p=localtime(&sekunnit);
4
90
    // this is Y2K compliant algorithm
4
91
    y = 1900 + p->tm_year;
4
92
4
93
    m = p->tm_mon + 1;
4
94
    day = p->tm_mday;
4
95
    h = 12;
4
96
4
97
    std::cout << "Input latitude, longitude and timezone\n";
4
98
    latit = LATITUDE;
4
99
    longit = LONGITUDE;
4
100
    // Timezone hours
4
101
    double tzone= TIMEZONE;
4
102
    double d = FNday(y, m, day, h);
4
103
4
104
    // Use FNsun to find the ecliptic longitude of the
4
105
    // Sun
4
106
    double lambda = FNsun(d);
4
107
4
108
    // Obliquity of the ecliptic
4
109
    double obliq = 23.439 * rads - .0000004 * rads * d;
4
110
4
111
    // Find the RA and DEC of the Sun
4
112
    double alpha = atan2(cos(obliq) * sin(lambda), cos(lambda));
4
113
    double delta = asin(sin(obliq) * sin(lambda));
4
114
4
115
    // Find the Equation of Time in minutes
4
116
    // Correction suggested by David Smith
4
117
    double LL = L - alpha;
4
118
    if (L < pi) LL += tpi;
4
119
    double equation = 1440.0 * (1.0 - LL / tpi);
4
120
    double ha = f0(latit,delta);
4
121
    double hb = f1(latit,delta);
4
122
    double twx = hb - ha;   // length of twilight in radians
4
123
    twx = 12.0*twx/pi;      // length of twilight in degrees
4
124
4
125
    // Conversion of angle to hours and minutes //
4
126
    daylen = degs * ha / 7.5;
4
127
    if (daylen<0.0001) {daylen = 0.0;}
4
128
    // arctic winter   //
4
129
4
130
    double riset = 12.0 - 12.0 * ha/pi + tzone - longit/15.0 + equation/60.0;
4
131
    double settm = 12.0 + 12.0 * ha/pi + tzone - longit/15.0 + equation/60.0;
4
132
    //double noont = riset + 12.0 * ha/pi;
4
133
    //double altmax = 90.0 + delta * degs - latit;
4
134
    // Correction suggested by David Smith
4
135
    // to express as degrees from the N horizon
4
136
4
137
    //if (delta * degs > latit ) altmax = 90.0 + latit - delta * degs;
4
138
4
139
    double twam = riset - twx;    // morning twilight begin
4
140
    double twpm = settm + twx;      // evening twilight end
4
141
4
142
    if (riset > 24.0) riset-= 24.0;
4
143
    if (settm > 24.0) settm-= 24.0;
4
144
4
145
    std::stringstream ss;
4
146
    ss << "\n Sunrise and set\n";
4
147
    ss << "===============\n";
4
148
    ss << "  year  : " << y << '\n';
4
149
    ss << "  month : " << m << '\n';
4
150
    ss << "  day   : " << day << "\n\n";
4
151
    ss << "Days until Y2K :  " << d << '\n';
4
152
    ss << "Latitude :  " << latit << ", longitude:  " << longit << '\n';
4
153
    ss << "Timezone :  " << tzone << "\n\n";
4
154
    ss << "Declination : " << delta * degs << '\n';
4
155
    ss << "Daylength   : "<< gethrmn(daylen).m_h<<":"<<gethrmn(daylen).m_min<< " hours \n";
4
156
    ss << "Begin civil twilight: "<<
4
157
                 gethrmn(twam).m_h<<":"<<gethrmn(twam).m_min; std::cout << '\n';
4
158
4
159
    ss << "Sunrise     : "<< gethrmn(riset).m_h<<":"<<gethrmn(riset).m_min; std::cout << '\n';
4
160
    ss << "Sun altitude at noontime ";
4
161
4
162
4
163
    ss << "Sunset      : "<<
4
164
                 gethrmn(settm).m_h<<":"<<gethrmn(settm).m_min; std::cout << '\n';
4
165
    ss << "Civil twilight: "<<
4
166
                 gethrmn(twpm).m_h<<":"<<gethrmn(twpm).m_min; std::cout << '\n';
4
167
    return ss.str();
4
168
}
169
170
void SunRiseSet::setPosition(double LATITUDE, double LONGITUDE, int TIMEZONE)
0
171
{
0
172
    this->LATITUDE = LATITUDE;
0
173
    this->LONGITUDE = LONGITUDE;
0
174
    this->TIMEZONE = TIMEZONE;
0
175
}
176
177
Clock SunRiseSet::getSunRise()
100
178
{
100
179
    double y,m,day,h,latit,longit;
100
180
    time_t sekunnit;
100
181
    struct tm *p;
100
182
    // get the date and time from the user
100
183
    // read system date and extract the year
100
184
100
185
    /** First get current time **/
100
186
    time(&sekunnit);
100
187
100
188
    /** Next get localtime **/
100
189
    p=localtime(&sekunnit);
100
190
    // this is Y2K compliant algorithm
100
191
    y = 1900 + p->tm_year;
100
192
    m = p->tm_mon + 1;
100
193
    day = p->tm_mday;
100
194
    h = 12;
100
195
    latit = LATITUDE;
100
196
    longit = LONGITUDE;
100
197
    // Timezone hours
100
198
    double tzone = TIMEZONE;
100
199
    double d = FNday(y, m, day, h);
100
200
    // Use FNsun to find the ecliptic longitude of the
100
201
    // Sun
100
202
    double lambda = FNsun(d);
100
203
    // Obliquity of the ecliptic
100
204
    double obliq = 23.439 * rads - .0000004 * rads * d;
100
205
    // Find the RA and DEC of the Sun
100
206
    double alpha = atan2(cos(obliq) * sin(lambda), cos(lambda));
100
207
    double delta = asin(sin(obliq) * sin(lambda));
100
208
    double LL = L - alpha;
100
209
    if (L < pi) LL += tpi;
100
210
    double equation = 1440.0 * (1.0 - LL / tpi);
100
211
    double ha = f0(latit,delta);
100
212
    // Conversion of angle to hours and minutes //
100
213
    daylen = degs * ha / 7.5;
100
214
    if (daylen<0.0001) {daylen = 0.0;}
100
215
    // arctic winter   //
100
216
    double riset = 12.0 - 12.0 * ha/pi + tzone - longit/15.0 + equation/60.0;
100
217
100
218
    if (riset > 24.0) riset-= 24.0;
100
219
    return  gethrmn(riset);
100
220
}
221
222
Clock SunRiseSet::getDayLength()
28
223
{
28
224
    double y,m,day,h,latit;
28
225
    time_t sekunnit;
28
226
    struct tm *p;
28
227
28
228
    // get the date and time from the user
28
229
    // read system date and extract the year
28
230
28
231
    /** First get current time **/
28
232
    time(&sekunnit);
28
233
28
234
    /** Next get localtime **/
28
235
    p=localtime(&sekunnit);
28
236
    // this is Y2K compliant algorithm
28
237
    y = 1900 + p->tm_year;
28
238
    m = p->tm_mon + 1;
28
239
    day = p->tm_mday;
28
240
    h = 12;
28
241
    latit = LATITUDE;
28
242
    double d = FNday(y, m, day, h);
28
243
28
244
    // Use FNsun to find the ecliptic longitude of the
28
245
    // Sun
28
246
    double lambda = FNsun(d);
28
247
    // Obliquity of the ecliptic
28
248
    double obliq = 23.439 * rads - .0000004 * rads * d;
28
249
    double delta = asin(sin(obliq) * sin(lambda));
28
250
    // Find the Equation of Time in minutes
28
251
    // Correction suggested by David Smith
28
252
    double ha = f0(latit,delta);
28
253
    // Conversion of angle to hours and minutes //
28
254
    daylen = degs * ha / 7.5;
28
255
    if (daylen<0.0001) {daylen = 0.0;}
28
256
    // arctic winter   //
28
257
28
258
    return  gethrmn(daylen);
28
259
}
260
261
Clock SunRiseSet::getSunSet()
50
262
{
50
263
    double y,m,day,h,latit,longit;
50
264
50
265
    time_t sekunnit;
50
266
    struct tm *p;
50
267
50
268
    // get the date and time from the user
50
269
    // read system date and extract the year
50
270
50
271
    /** First get current time **/
50
272
    time(&sekunnit);
50
273
50
274
    /** Next get localtime **/
50
275
50
276
    p=localtime(&sekunnit);
50
277
    // this is Y2K compliant algorithm
50
278
    y = 1900 + p->tm_year;
50
279
50
280
    m = p->tm_mon + 1;
50
281
    day = p->tm_mday;
50
282
    h = 12;
50
283
50
284
    latit = LATITUDE;
50
285
    longit = LONGITUDE;
50
286
    // Timezone hours
50
287
    double tzone = TIMEZONE;
50
288
50
289
    double d = FNday(y, m, day, h);
50
290
50
291
    // Use FNsun to find the ecliptic longitude of the
50
292
    // Sun
50
293
50
294
    double lambda = FNsun(d);
50
295
50
296
    // Obliquity of the ecliptic
50
297
50
298
    double obliq = 23.439 * rads - .0000004 * rads * d;
50
299
50
300
    // Find the RA and DEC of the Sun
50
301
50
302
    double alpha = atan2(cos(obliq) * sin(lambda), cos(lambda));
50
303
    double delta = asin(sin(obliq) * sin(lambda));
50
304
50
305
50
306
    // Find the Equation of Time in minutes
50
307
    // Correction suggested by David Smith
50
308
50
309
    double LL = L - alpha;
50
310
    if (L < pi) LL += tpi;
50
311
    double equation = 1440.0 * (1.0 - LL / tpi);
50
312
50
313
50
314
    double ha = f0(latit,delta);
50
315
50
316
    // Conversion of angle to hours and minutes //
50
317
    daylen = degs * ha / 7.5;
50
318
    if (daylen<0.0001) {daylen = 0.0;}
50
319
    // arctic winter   //
50
320
50
321
    //double riset = 12.0 - 12.0 * ha/pi + tzone - longit/15.0 + equation/60.0;
50
322
    double settm = 12.0 + 12.0 * ha/pi + tzone - longit/15.0 + equation/60.0;
50
323
50
324
    //if (riset > 24.0) riset-= 24.0;
50
325
    if (settm > 24.0) settm-= 24.0;
50
326
    return  gethrmn(settm);
50
327
}
/home/pi/programowanie/iDom_server_OOP/libs/useful/test/../useful.h
1
#ifndef Iusefull_H
2
#define Iusefull_H
3
4
#include <iostream>
5
#include <string>
6
#include <vector>
7
#include <ostream>
8
#include <chrono>
9
#include <sstream>
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <iomanip>
13
#ifndef ANDROID
14
#include "json.hpp"
15
#endif
16
17
std::vector<std::string> split_string(const std::string& s, char separator );
18
19
class useful_F_libs {
20
public:
21
    static  void write_to_mkfifo(const std::string& path, const std::string &msg);
22
    static  std::string read_from_mkfifo(const std::string &path);
23
    static size_t  WriteCallback(void *contents, size_t size, size_t nmemb, void *userp);
24
    static std::string find_tag (const std::string &temp);
25
    //////////////////// HTTP req //////////////////////////
26
    static std::string httpPost(const std::string &url, int timeoutSeconds);
27
    static std::string httpPost(const std::string &url);
28
    static void downloadFile(const std::string &url, const std::string &path, int timeoutSeconds);
29
    static std::string replaceAll(std::string str, const std::string& from, const std::string& to);
30
    static std::string removeHtmlTag(std::string &data);
31
    /////////////////////  JSON ////////////////////////////
32
33
#ifndef ANDROID
34
    static nlohmann::json getJson(const std::string &url);
35
#endif
36
};
37
namespace std
38
{
39
40
#ifdef ANDROID
41
template <typename T>
42
int stoi(T s){
43
    return atoi(s.c_str());
44
}
45
#endif
46
47
template <typename T>
48
std::string to_string(T value)
49
{
50
    std::ostringstream os;
51
    os << value;
52
    return os.str();
53
}
54
} // namespace std
55
56
template <typename T>
57
std::string to_string_with_precision(const T a_value, const int n = 4)
212
58
{
212
59
    std::ostringstream out;
212
60
    out << std::setprecision(n) << a_value;
212
61
    return out.str();
212
62
}
63
64
struct Clock{
65
private:
66
    std::time_t m_time;
67
#ifdef BT_TEST
68
    static unsigned int m_BT_H;
69
    static unsigned int m_BT_M;
70
#endif
71
public:
72
    unsigned int m_h = 0;
73
    unsigned int m_min = 0;
2.70k
74
    Clock () {}
148
75
    Clock(std::string t){
148
76
        std::vector<std::string> vt = split_string(t,':');
148
77
        int h = std::stoi(vt.at(0));
148
78
        int m = std::stoi(vt.at(1));
148
79
        set(static_cast <unsigned int>(h),static_cast <unsigned int>(m));
148
80
    }
81
2.07k
82
    Clock(unsigned int h, unsigned int m) {
2.07k
83
        set(h,m);
2.07k
84
    }
85
    /////////////////////////////////////////////////////////////////////////////////////
2.22k
86
    void set(unsigned int h, unsigned int m){
2.22k
87
        if (h<24 && m <60){
2.22k
88
            this->m_h = h;
2.22k
89
            this->m_min = m;
2.22k
90
        }
4
91
        else {
4
92
            throw 0;
4
93
        }
2.22k
94
    }
95
96
    /////////////////////////////////////////////////////////////////////////////////////
296
97
    const std::string getString(){
296
98
        std::stringstream ret;
296
99
        if (m_h < 10) {
224
100
            ret << "0";
224
101
        }
296
102
        ret << m_h;
296
103
        ret << ":";
296
104
        if (m_min < 10) {
162
105
            ret << "0";
162
106
        }
296
107
        ret << m_min;
296
108
        return ret.str();
296
109
    }
110
    /////////////////////////////////////////////////////////////////////////////////////
52
111
    bool operator == (const Clock & c){
52
112
        if ((this->m_h == c.m_h) && (this->m_min == c.m_min)){
44
113
            return true;
44
114
        }
8
115
        else{
8
116
            return false;
8
117
        }
52
118
    }
119
    /////////////////////////////////////////////////////////////////////////////////////
52
120
    bool operator != (const Clock & c){
52
121
        if ((this->m_h != c.m_h) || (this->m_min != c.m_min)){
32
122
            return true;
32
123
        }
20
124
        else{
20
125
            return false;
20
126
        }
52
127
    }
128
    /////////////////////////////////////////////////////////////////////////////////////
4
129
    friend std::ostream & operator<< (std::ostream &w ,  Clock &c) {
4
130
        return w << c.getString();
4
131
    }
132
    /////////////////////////////////////////////////////////////////////////////////////
72
133
    bool operator < (const Clock& c){
72
134
        if (this->m_h < c.m_h){
54
135
            return true;
54
136
        }
18
137
        else{
18
138
            if (this->m_h == c.m_h && this->m_min < c.m_min){
4
139
                return true;
4
140
            }
18
141
        }
14
142
        return false;
72
143
    }
144
    /////////////////////////////////////////////////////////////////////////////////////
22
145
    bool operator > (const Clock& c){
22
146
        if (this->m_h > c.m_h){
10
147
            return true;
10
148
        }
12
149
        else{
12
150
            if (this->m_h == c.m_h && this->m_min > c.m_min){
4
151
                return true;
4
152
            }
12
153
        }
8
154
        return false;
22
155
    }
156
    /////////////////////////////////////////////////////////////////////////////////////
20
157
    bool operator >= (const Clock& c){
20
158
        if (this->m_h > c.m_h){
8
159
            return true;
8
160
        }
12
161
        else if (this->m_h == c.m_h){
4
162
4
163
            if (this->m_min >= c.m_min){
4
164
                return true;
4
165
            }
4
166
        }
8
167
        return false;
20
168
    }
169
    /////////////////////////////////////////////////////////////////////////////////////
28
170
    bool operator <= (const Clock& c){
28
171
        if (this->m_h < c.m_h){
8
172
            return true;
8
173
        }
20
174
        else if (this->m_h == c.m_h){
8
175
8
176
            if (this->m_min <= c.m_min){
4
177
                return true;
4
178
            }
8
179
        }
16
180
        return false;
28
181
    }
182
    /////////////////////////////////////////////////////////////////////////////////////
524
183
    Clock  operator + (const Clock& c){
524
184
        unsigned int minutes, hours;
524
185
        minutes = m_min+ c.m_min;
524
186
        hours = m_h + c.m_h;
524
187
        if (minutes >59){
503
188
            minutes =  minutes % 60;
503
189
            hours+=1;
503
190
        }
524
191
        if (hours >= 24){
503
192
            hours-=24;
503
193
        }
524
194
        return  Clock(hours, minutes);
524
195
524
196
    }
197
    /////////////////////////////////////////////////////////////////////////////////////
20
198
    Clock&  operator += (const Clock& c){
20
199
        unsigned int minutes, hours;
20
200
        minutes = m_min+ c.m_min;
20
201
        hours = m_h + c.m_h;
20
202
        if (minutes >59){
16
203
            minutes =  minutes % 60;
16
204
            hours+=1;
16
205
        }
20
206
        if (hours >= 24){
16
207
            hours-=24;
16
208
        }
20
209
        this->m_h = hours;
20
210
        this->m_min = minutes;
20
211
        return *this;
20
212
20
213
    }
214
    /////////////////////////////////////////////////////////////////////////////////////
215
20
216
    unsigned int toSeconds(){
20
217
        return toSeconds(Clock(this->m_h, this->m_min) );
20
218
    }
219
    /////////////////////////////////////////////////////////////////////////////////////
220
24
221
    static unsigned int toSeconds(Clock t){
24
222
        return ((t.m_h*60) + t.m_min)*60;
24
223
    }
224
    /////////////////////////////////////////////////////////////////////////////////////
225
12
226
    static Clock fromSeconds(unsigned int sec){
12
227
        unsigned int h = sec/3600;
12
228
        unsigned int min = sec%3600;
12
229
        min = min/60;
12
230
        return Clock(h,min);
12
231
    }
232
    /////////////////////////////////////////////////////////////////////////////////////
233
234
    static Clock periodOfTime(Clock start, Clock end)
8
235
    {
8
236
        if (end >= start){
4
237
            return Clock::fromSeconds(end.toSeconds() - start.toSeconds()  );
4
238
        }
4
239
        else{
4
240
            return Clock::fromSeconds(end.toSeconds() + ( Clock::toSeconds(Clock(23,59))+ 60 - start.toSeconds() ) );
4
241
        }
8
242
        //return diff;
8
243
    }
244
    ////////////////////////////////////////////////////////////////////////////////////
245
    static unsigned int getUnixTime()
246
    {
247
        return static_cast<unsigned int> (std::time(nullptr));
248
    }
249
    /////////////////////////////////////////////////////////////////////////////////////
250
#ifdef BT_TEST
251
    static void setTime_forBT_usage(int h, int m)
252
    {
253
        m_BT_H = h;
254
        m_BT_M = m;
255
    }
256
#endif
257
    /////////////////////////////////////////////////////////////////////////////////////
258
    static Clock getTime()
732
259
    {
732
260
#ifdef BT_TEST
732
261
        return Clock(m_BT_H,m_BT_M);
732
262
#else
263
        time_t now = time(0);
264
        tm *ltm = localtime(&now);
265
        return Clock( static_cast <unsigned int>(ltm->tm_hour),static_cast <unsigned int>(ltm->tm_min) );
266
#endif
732
267
    }
268
    /////////////////////////////////////////////////////////////////////////////////////
269
    void stopwatchStart()
4
270
    {
4
271
        m_time = std::time(nullptr);
4
272
    }
273
    /////////////////////////////////////////////////////////////////////////////////////
274
    unsigned int  stopwatchStopAndGetResult()
4
275
    {
4
276
        return static_cast<unsigned int>(std::time(nullptr) - m_time);
4
277
    }
278
};
279
280
enum class STATE {
281
    OFF,
282
    ON,
283
    UNKNOWN,
284
    PLAY,
285
    PAUSE,
286
    STOP,
287
    ACTIVE,
288
    DEACTIVE,
289
    WORKING,
290
    DEFINE,
291
    UNDEFINE,
292
    LOCK,
293
    UNLOCK,
294
    EMPTY,
295
    FULL,
296
    SEND_OK,
297
    SEND_NOK
298
    //WARNING remember add new state to stateToString() usefull.cpp
299
};
300
301
302
std::string stateToString(STATE s);
303
STATE stringToState(const std::string& s);
304
305
#endif
/home/pi/programowanie/iDom_server_OOP/libs/useful/test/useful_bt.cpp
1
#include <gtest/gtest.h>
2
#include <gmock/gmock.h>
3
#include <sys/types.h>
4
#include <sys/stat.h>
5
#include <stdio.h>
6
#include <string.h>
7
#include <fcntl.h>
8
#include <unistd.h>
9
#include "../useful.h"
10
///////////////////////////////////////////////////// TEST ///////////////////////////////////////////////////////\
11
12
TEST(ClockClass, AddTwoHours)
4
13
{
4
14
    Clock f(13,57);
4
15
    Clock g(23,59);
4
16
    Clock r = f+g;
4
17
    EXPECT_EQ(r.getString(), "13:56");
4
18
}
19
20
TEST(ClockClass, lessThen_Hours)
4
21
{
4
22
    Clock f(13,57);
4
23
    Clock g(23,59);
4
24
    EXPECT_EQ(f<g, true);
4
25
}
26
27
TEST(ClockClass, plus_operator)
4
28
{
4
29
    Clock f(13,57);
4
30
    f+=Clock("04:04");
4
31
    EXPECT_EQ(f.getString(),"18:01");
4
32
}
33
34
TEST(ClockClass, _operator)
4
35
{
4
36
    EXPECT_FALSE(Clock("04:04") == Clock("04:05"));
4
37
    EXPECT_FALSE(Clock("05:05") == Clock("04:05"));
4
38
    EXPECT_TRUE(Clock("05:05") == Clock("05:05"));
4
39
    EXPECT_FALSE(Clock("05:05") != Clock("05:05"));
4
40
    EXPECT_TRUE(Clock("04:05") != Clock("05:05"));
4
41
    EXPECT_TRUE(Clock("04:05") != Clock("04:04"));
4
42
    EXPECT_TRUE(Clock("04:05") > Clock("04:04"));
4
43
    EXPECT_FALSE(Clock("03:05") > Clock("04:04"));
4
44
    EXPECT_TRUE(Clock("04:05") >= Clock("04:04"));
4
45
    EXPECT_FALSE(Clock("04:05") <= Clock("04:04"));
4
46
    EXPECT_FALSE(Clock("05:05") <= Clock("04:05"));
4
47
    EXPECT_TRUE(Clock("03:05") <= Clock("04:05"));
4
48
    EXPECT_TRUE(Clock("04:05") <= Clock("04:06"));
4
49
    EXPECT_FALSE(Clock("05:05") < Clock("04:06"));
4
50
    EXPECT_TRUE(Clock("04:05") < Clock("04:06"));
4
51
    EXPECT_TRUE(Clock("08:05") > Clock("04:06"));
4
52
4
53
    std::stringstream s;
4
54
    Clock f("00:00");
4
55
    s << f;
4
56
    EXPECT_STREQ("00:00", s.str().c_str());
4
57
4
58
    Clock g("20:00");
4
59
    f = g.getTime();
4
60
    g += Clock("23:43");
4
61
    EXPECT_STREQ("19:43", g.getString().c_str());
4
62
}
63
64
TEST(ClockClass, periodOfTime)
4
65
{
4
66
    Clock f(13,57);
4
67
    Clock g(22,22);
4
68
    Clock r = Clock::periodOfTime(f,g);
4
69
    EXPECT_EQ(r.getString(),"08:25");
4
70
    r = Clock::periodOfTime(g,f);
4
71
    EXPECT_EQ(r.getString(),"15:35");
4
72
}
73
74
TEST(ClockClass, from_to_second)
4
75
{
4
76
    Clock f;
4
77
    f.set(13,57);
4
78
    unsigned int sec = f.toSeconds();
4
79
    Clock g = Clock::fromSeconds(sec);
4
80
    EXPECT_EQ(f.getString(),g.getString());
4
81
}
82
83
TEST(ClockClass, stopwatch)
4
84
{
4
85
    Clock f;
4
86
    f.stopwatchStart();
4
87
    sleep(2);
4
88
    EXPECT_EQ(2,f.stopwatchStopAndGetResult());
4
89
}
90
91
TEST(ClockClass, wrongSet)
4
92
{
4
93
    Clock f;
4
94
    EXPECT_ANY_THROW(f.set(99,99));
4
95
}
96
97
TEST(ClockClass, to_string_with_precision_TC)
4
98
{
4
99
    double d = 1.0/3.0;
4
100
    EXPECT_STREQ("0.33", to_string_with_precision(d,2).c_str() );
4
101
}
102
103
TEST(JSON, getJSON)
4
104
{
4
105
    nlohmann::json test_JSON = useful_F_libs::getJson("http://cyniu88.no-ip.pl/test/json/on_lightning.json");
4
106
    auto testKey = test_JSON["success"].get<bool>();
4
107
4
108
    std::cout << " JSON JEST" << std::endl << test_JSON.dump(4) << std::endl;
4
109
4
110
    EXPECT_TRUE(testKey);
4
111
}
112
/*
113
TEST(mkfifo_test, mkfifoFile)
114
{
115
    std::string path = "/mnt/ramdisk/FifoFile";
116
    std::string msg = "+";
117
    std::string returnString;
118
    int temp = mkfifo(path.c_str(),0666);
119
120
    if ( temp == -1)
121
        std::cout << "plik istnieje "<<strerror(errno)<< std::endl;
122
    else if (temp == 0)
123
        std::cout << "plik stworzony"<< std::endl;
124
    else
125
        FAIL();
126
    useful_F_libs::write_to_mkfifo(path,msg);
127
128
    returnString = useful_F_libs::read_from_mkfifo(path);
129
    unlink(path.c_str());
130
131
   // EXPECT_STREQ(returnString.c_str(), msg.c_str()) << "odczytano smieci";
132
    //TODO not
133
134
}
135
*/
/home/pi/programowanie/iDom_server_OOP/libs/useful/usefull.cpp
1
#include "useful.h"
2
#include <sys/fcntl.h>
3
#include <unistd.h>
4
#include <sys/types.h>
5
#include <sys/stat.h>
6
#include <fcntl.h>
7
#ifndef IDOM
8
#include <curl/curl.h>
9
#endif
148
10
std::vector<std::string> split_string(const std::string& s, char separator ){
148
11
    std::vector<std::string> output;
148
12
    std::string::size_type prev_pos = 0, pos = 0;
148
13
296
14
    while((pos = s.find(separator, pos)) != std::string::npos)
148
15
    {
148
16
        std::string substring( s.substr(prev_pos, pos-prev_pos) );
148
17
        output.push_back(substring);
148
18
        prev_pos = ++pos;
148
19
    }
148
20
    try {
148
21
        output.push_back(s.substr(prev_pos, pos-prev_pos)); // Last word
148
22
    }
0
23
    catch (...){
0
24
0
25
    }
148
26
    return output;
148
27
}
28
2.36k
29
std::string stateToString(STATE s){
0
30
    switch (s) {
132
31
    case STATE::OFF:        return "OFF";
64
32
    case STATE::ON:         return "ON";
36
33
    case STATE::PLAY:       return "PLAY";
4
34
    case STATE::PAUSE:      return "PAUSE";
0
35
    case STATE::STOP:       return "STOP";
36
36
    case STATE::ACTIVE:     return "ACTIVE";
140
37
    case STATE::DEACTIVE:   return "DEACTIVE";
12
38
    case STATE::WORKING:    return "WORKING";
0
39
    case STATE::DEFINE:     return "DEFINE";
1.51k
40
    case STATE::UNDEFINE:   return "UNDEFINE";
152
41
    case STATE::LOCK:       return "LOCK";
144
42
    case STATE::UNLOCK:     return "UNLOCK";
0
43
    case STATE::EMPTY:      return "EMPTY";
0
44
    case STATE::FULL:       return "FULL";
0
45
    case STATE::SEND_OK:    return "SEND_OK";
0
46
    case STATE::SEND_NOK:   return "SEND_NOK";
136
47
    default:
136
48
        return "UNKNOWN";
0
49
    }
2.36k
50
}
51
5.31k
52
STATE stringToState(const std::string& s){
5.31k
53
    if(s == "OFF")
1.04k
54
        return STATE::OFF;
4.26k
55
    else if (s == "ON")
1.04k
56
        return STATE::ON;
3.21k
57
    else if (s == "PLAY")
0
58
        return STATE::PLAY;
3.21k
59
    else if (s == "PAUSE")
0
60
        return STATE::PAUSE;
3.21k
61
    else if (s == "STOP")
0
62
        return STATE::STOP;
3.21k
63
    else if (s == "ACTIVE")
0
64
        return STATE::ACTIVE;
3.21k
65
    else if (s == "DEACTIVE")
0
66
        return STATE::DEACTIVE;
3.21k
67
    else if (s == "WORKING")
0
68
        return STATE::WORKING;
3.21k
69
    else if (s == "DEFINE")
0
70
        return STATE::DEFINE;
3.21k
71
    else if (s == "UNDEFINE")
0
72
        return STATE::UNDEFINE;
3.21k
73
    else if (s == "LOCK")
0
74
        return STATE::LOCK;
3.21k
75
    else if (s == "UNLOCK")
0
76
        return STATE::UNLOCK;
3.21k
77
    else if (s == "EMPTY")
0
78
        return STATE::EMPTY;
3.21k
79
    else if (s == "FULL")
0
80
        return STATE::FULL;
3.21k
81
    else if (s == "SEND_OK")
0
82
        return STATE::SEND_OK;
3.21k
83
    else if (s == "SEND_NOK")
0
84
        return STATE::SEND_NOK;
3.21k
85
    else
3.21k
86
        return STATE::UNKNOWN;
5.31k
87
}
88
89
#ifndef IDOM
90
void useful_F_libs::write_to_mkfifo(const std::string &path, const std::string& msg)
24
91
{
24
92
    errno = 0;
24
93
    int fd = open(path.c_str(), O_RDWR| O_NONBLOCK );
24
94
    std::cout <<"write open file: " << fd << " path " << path.c_str() << " msg: " << msg <<std::endl;
24
95
    std::cout <<  "write_to_mkfifo( error - " << strerror(  errno ) <<   std::endl;
24
96
    write(fd, msg.c_str(), msg.size());
24
97
    close(fd);
24
98
}
99
100
std::string useful_F_libs::read_from_mkfifo(const std::string& path)
40
101
{
40
102
    char buf[10];
40
103
    /* open, read, and display the message from the FIFO */
40
104
    int fd = open(path.c_str(), O_RDONLY | O_NONBLOCK);
40
105
    std::cout <<"read open file: " << fd <<std::endl;
40
106
    read(fd, buf, 10);
40
107
    std::cout << "buf: " << buf << std::endl;
40
108
    close(fd);
40
109
    return (std::string(buf));
40
110
}
111
112
size_t useful_F_libs::WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
216
113
{
216
114
    ((std::string*)userp)->append((char*)contents, size * nmemb);
216
115
    return size * nmemb;
216
116
}
117
118
std::string useful_F_libs::find_tag(const std::string& temp)
52
119
{
52
120
    std::string value = "";
1.09k
121
    for (unsigned int i = 0; i<temp.size();++i){
1.09k
122
1.09k
123
        if (temp.at(i) =='>')
52
124
        {  int z = i+1;
156
125
            while (temp.at(z)!='<')
104
126
            {
104
127
                value+= temp.at(z);
104
128
                ++z;
104
129
            }
52
130
            break;
52
131
        }
1.09k
132
    }
52
133
    return value;
52
134
}
135
136
#ifndef BT_TEST
137
std::string useful_F_libs::httpPost(const std::string& url, int timeoutSeconds)
138
{
139
    CURL *curl;
140
    CURLcode res;
141
    std::string readBuffer;
142
    curl = curl_easy_init();
143
144
    if(curl) {
145
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeoutSeconds);
146
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
147
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, useful_F_libs::WriteCallback);
148
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
149
        res = curl_easy_perform(curl);
150
        /* Check for errors */
151
        if(res != CURLE_OK)
152
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
153
                    curl_easy_strerror(res));
154
155
        /* always cleanup */
156
        curl_easy_cleanup(curl);
157
    }
158
    curl_global_cleanup();
159
160
    return readBuffer;
161
}
162
163
std::string useful_F_libs::httpPost(const std::string& url)
164
{
165
    return useful_F_libs::httpPost(url, 10);
166
}
167
#endif
168
169
void useful_F_libs::downloadFile(const std::string& url, const std::string& path, int timeoutSeconds)
0
170
{
0
171
    CURL *curl;
0
172
    //CURLcode res;
0
173
0
174
    curl = curl_easy_init();
0
175
    if (curl) {
0
176
        FILE *fp = fopen(path.c_str(),"wb");
0
177
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeoutSeconds);
0
178
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
0
179
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
0
180
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
0
181
        //res = curl_easy_perform(curl);
0
182
        /* always cleanup */
0
183
        curl_easy_cleanup(curl);
0
184
        fclose(fp);
0
185
    }
0
186
}
187
12
188
std::string useful_F_libs::replaceAll(std::string str, const std::string& from, const std::string& to) {
12
189
    size_t start_pos = 0;
44
190
    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
32
191
        str.replace(start_pos, from.length(), to);
32
192
        start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
32
193
    }
12
194
    return str;
12
195
}
196
std::string useful_F_libs::removeHtmlTag(std::string &data)
8
197
{
8
198
    data = useful_F_libs::replaceAll(data,"</dl>","\n");
8
199
8
200
    //data = useful_F::replaceAll(data,"    "," ");
8
201
    bool copy = true;
8
202
    std::string plainString = "";
8
203
    std::stringstream convertStream;
8
204
8
205
    // remove all xml tags
11.5k
206
    for (unsigned int i=0; i < data.length(); i++)
11.5k
207
    {
11.5k
208
        convertStream << data[i];
11.5k
209
11.5k
210
        if(convertStream.str().compare("<") == 0) copy = false;
11.4k
211
        else if(convertStream.str().compare(">") == 0)
76
212
        {
76
213
            copy = true;
76
214
            convertStream.str(std::string());
76
215
            continue;
76
216
        }
11.5k
217
11.4k
218
        if(copy) plainString.append(convertStream.str());
11.4k
219
11.4k
220
        convertStream.str(std::string());
11.4k
221
    }
8
222
8
223
    return plainString;
8
224
}
225
226
nlohmann::json useful_F_libs::getJson(const std::string& url)
16
227
{
16
228
    std::string str = useful_F_libs::httpPost(url);
16
229
    nlohmann::json jj = nlohmann::json::parse( str);
16
230
16
231
    return jj;
16
232
}
233
#endif
/home/pi/programowanie/iDom_server_OOP/src/433MHz/RFLink/../../functions/../blockQueue/../logger/logger.hpp
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
16
84
    {
16
85
        *static_cast<std::ostringstream *>(this) << t;
16
86
        return (*this);
16
87
    }
_ZN6LoggerlsIA29_cEERS_RKT_
8
84
    {
8
85
        *static_cast<std::ostringstream *>(this) << t;
8
86
        return (*this);
8
87
    }
_ZN6LoggerlsIA25_cEERS_RKT_
8
84
    {
8
85
        *static_cast<std::ostringstream *>(this) << t;
8
86
        return (*this);
8
87
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/home/pi/programowanie/iDom_server_OOP/src/433MHz/RFLink/../../functions/../c_connection/../iDom_server_OOP.h
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
68
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
24
41
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    RADIO_EQ_CONTAINER *main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/home/pi/programowanie/iDom_server_OOP/src/433MHz/RFLink/TEST/rflinkhandler_BT.cpp
1
#include <gtest/gtest.h>
2
3
#include "../rflinkhandler.h"
4
#include "test_data.h"
5
6
class RFLinkHandler_Class_fixture : public ::testing::Test
7
{
8
public:
9
    thread_data test_my_data;
10
    config test_server_set;
11
    iDomSTATUS test_status;
12
    RFLinkHandler* test_RFLink;
13
14
    void SetUp() final
20
15
    {
20
16
        test_server_set.TS_KEY = "key test";
20
17
        test_server_set.RFLinkBaudRate = "57600";
20
18
        test_server_set.RFLinkPort = "/dev/fakePortRS232";
20
19
        test_my_data.server_settings = &test_server_set;
20
20
        test_my_data.main_iDomStatus = &test_status;
20
21
        test_RFLink = new RFLinkHandler(&test_my_data);
20
22
    }
23
    void TearDown() final
20
24
    {
20
25
        delete test_RFLink;
20
26
    }
27
};
28
29
TEST_F(RFLinkHandler_Class_fixture, sendCommandAndWaitForReceive)
4
30
{
4
31
    test_RFLink->init();
4
32
    std::string k("msg_test;\n a=4:b=10;\n");
4
33
    SerialPi_set_recv_msg(k);
4
34
    std::string r = test_RFLink->sendCommandAndWaitForReceive("test command");
4
35
4
36
    EXPECT_STREQ(r.c_str(),"msg_test;");
4
37
    r = test_RFLink->sendCommandAndWaitForReceive("ok");
4
38
    EXPECT_STREQ(r.c_str()," a=4:b=10;");
4
39
}
40
41
TEST_F(RFLinkHandler_Class_fixture, port_does_not_exist)
4
42
{
4
43
    bool result =  test_RFLink->init();
4
44
    EXPECT_FALSE(result);
4
45
}
46
47
TEST_F(RFLinkHandler_Class_fixture, port_exist)
4
48
{
4
49
    test_server_set.RFLinkPort = "/dev/tty0";
4
50
    bool result =  test_RFLink->init();
4
51
    EXPECT_TRUE(result);
4
52
}
53
54
TEST_F(RFLinkHandler_Class_fixture, getValue)
4
55
{
4
56
    std::string m  = "20;90;Alecto V4;ID=557a;TEMP=0057;HUM=25;";
4
57
    EXPECT_STREQ(test_RFLink->getArgumentValueFromRFLinkMSG(m,"ID").c_str(),"557a");
4
58
    EXPECT_STREQ(test_RFLink->getArgumentValueFromRFLinkMSG(m,"TEMP").c_str(),"0057");
4
59
    EXPECT_THROW(test_RFLink->getArgumentValueFromRFLinkMSG(m,"test"),std::string);
4
60
}
61
62
TEST_F(RFLinkHandler_Class_fixture, readAndFlush)
4
63
{
4
64
    SerialPi_set_recv_msg("doTest;\n");
4
65
    std::string retStr = test_RFLink->readFromRS232();
4
66
    EXPECT_STREQ(retStr.c_str(), "doTest;");
4
67
4
68
    SerialPi_set_recv_msg("doTest2;\n");
4
69
    test_RFLink->flush();
4
70
    retStr = test_RFLink->readFromRS232();
4
71
    EXPECT_EQ(retStr.size(), 0);
4
72
}
/home/pi/programowanie/iDom_server_OOP/src/433MHz/RFLink/rflinkhandler.cpp
1
#include <unistd.h>
2
3
#include "rflinkhandler.h"
4
#include "../../functions/functions.h"
5
6
std::mutex RFLinkHandler::sm_RFLink_MUTEX;
7
std::string RFLinkHandler::sm_RFLink_BUFOR;
8
9
10
RFLinkHandler::RFLinkHandler(thread_data *my_data):
11
    serial_RFLink(my_data->server_settings->RFLinkPort)
196
12
{
196
13
    this->my_data = my_data;
196
14
#ifdef BT_TEST
196
15
    std::cout << "RFLinkHandler::RFLinkHandler()"<<std::endl;
196
16
#endif
196
17
}
18
19
bool RFLinkHandler::init()
12
20
{
12
21
    if( access( my_data->server_settings->RFLinkPort.c_str(), F_OK ) != -1 )
4
22
    {
4
23
        serial_RFLink.begin( std::stoi(my_data->server_settings->RFLinkBaudRate));
4
24
        log_file_mutex.mutex_lock();
4
25
        log_file_cout << INFO <<"otwarcie portu RS232 RFLink " << my_data->server_settings->RFLinkPort << "  "
4
26
                      <<my_data->server_settings->RFLinkBaudRate<<std::endl;
4
27
        log_file_mutex.mutex_unlock();
4
28
        return true;
4
29
    }
12
30
    else
8
31
    {
8
32
        log_file_mutex.mutex_lock();
8
33
        log_file_cout << ERROR <<"brak portu RS232 RFLink " << my_data->server_settings->RFLinkPort<<std::endl;
8
34
        log_file_mutex.mutex_unlock();
8
35
        return false;
8
36
    }
12
37
}
38
39
void RFLinkHandler::flush()
4
40
{
4
41
    serial_RFLink.flush();
4
42
}
43
44
void RFLinkHandler::sendCommand(std::string cmd)
4
45
{
4
46
    std::lock_guard<std::mutex> m_lock(sm_RFLink_MUTEX);
4
47
    cmd.append("\n\r"); // add NL & CR
4
48
    serial_RFLink.print(cmd.c_str());
4
49
}
50
51
std::string RFLinkHandler::sendCommandAndWaitForReceive(std::string cmd)
8
52
{
8
53
    std::lock_guard<std::mutex> m_lock(sm_RFLink_MUTEX);
8
54
    cmd.append("\n\r"); // add NL & CR
8
55
    serial_RFLink.print(cmd.c_str());
8
56
    return internalReadFromRS232();
8
57
}
58
59
std::string RFLinkHandler::readFromRS232()
8
60
{
8
61
    std::lock_guard<std::mutex> m_lock(sm_RFLink_MUTEX);
8
62
    return internalReadFromRS232();
8
63
}
64
65
std::string RFLinkHandler::internalReadFromRS232()
16
66
{
16
67
    std::string buf;
16
68
16
69
    if(serial_RFLink.available() > 0){
116
70
        while (true){
116
71
116
72
            char b = serial_RFLink.read();
116
73
            if (b == '\n'){
12
74
                break;
12
75
            }
104
76
            buf += b;
104
77
        }
12
78
    }
16
79
    return buf;
16
80
}
81
82
std::string RFLinkHandler::getArgumentValueFromRFLinkMSG(const std::string& msg, const std::string& var)
256
83
{
256
84
    std::string id;
256
85
256
86
    int pos = msg.find(var+"=");
256
87
    if (pos == -1 ){
76
88
        throw "argument \""+var+"\" not found";
76
89
    }
180
90
    if (msg.at(0) != '2' || msg.at(1) != '0'){
4
91
        throw WRONG_FORMAT();
4
92
    }
180
93
#ifdef BT_TEST
176
94
    std::cout << "znaleziono " << var <<" na pozycji " << pos <<std::endl;
176
95
#endif
176
96
1.06k
97
    for (int i = 1+pos+var.size();;++i ){
1.06k
98
        char t = msg.at(i);
1.06k
99
        if (t ==';'){
176
100
            break;
176
101
        }
884
102
        id += t;
884
103
    }
176
104
    return id;
180
105
180
106
}
/home/pi/programowanie/iDom_server_OOP/src/LCD_c/test/lcd_c_stub.cpp
1
#include <iostream>
2
#include "../lcd_c.h"
3
220
4
void LCD_c::set_print_song_state(int i){
220
5
    std::cout << "LCD_c::set_print_song_state(int i)" << i <<std::endl;
220
6
}
/home/pi/programowanie/iDom_server_OOP/src/RADIO_433_eq/../433MHz/../functions/../blockQueue/../logger/logger.hpp
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
28
84
    {
28
85
        *static_cast<std::ostringstream *>(this) << t;
28
86
        return (*this);
28
87
    }
_ZN6LoggerlsIA30_cEERS_RKT_
8
84
    {
8
85
        *static_cast<std::ostringstream *>(this) << t;
8
86
        return (*this);
8
87
    }
_ZN6LoggerlsIA31_cEERS_RKT_
12
84
    {
12
85
        *static_cast<std::ostringstream *>(this) << t;
12
86
        return (*this);
12
87
    }
_ZN6LoggerlsIA39_cEERS_RKT_
8
84
    {
8
85
        *static_cast<std::ostringstream *>(this) << t;
8
86
        return (*this);
8
87
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/home/pi/programowanie/iDom_server_OOP/src/RADIO_433_eq/../433MHz/../functions/../c_connection/../iDom_server_OOP.h
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
16
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
8
41
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    RADIO_EQ_CONTAINER *main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/home/pi/programowanie/iDom_server_OOP/src/RADIO_433_eq/radio_433_eq.cpp
1
#include <iostream>
2
#include <fstream>
3
#include <sstream>
4
#include "radio_433_eq.h"
5
6
RADIO_SWITCH::RADIO_SWITCH(thread_data *my_data, const RADIO_EQ_CONFIG &cfg, RADIO_EQ_TYPE type):
7
    main433MHz(my_data)
2.65k
8
{
2.65k
9
    puts("RADIO_SWITCH::RADIO_SWITCH()");
2.65k
10
    RADIO_EQ::m_my_data = my_data;
2.65k
11
    RADIO_EQ::m_type = type;
2.65k
12
    RADIO_EQ::m_config = cfg;
2.65k
13
    m_sunrise = stringToState(cfg.sunrise);
2.65k
14
    m_sunset  = stringToState(cfg.sunset);
2.65k
15
}
16
17
RADIO_SWITCH::~RADIO_SWITCH()
2.65k
18
{
2.65k
19
    puts("RADIO_SWITCH::~RADIO_SWITCH()");
2.65k
20
}
21
22
void RADIO_SWITCH::on()
48
23
{
48
24
    main433MHz.sendCode(RADIO_EQ::m_config.onCode);
48
25
    m_state = STATE::ON;
48
26
    RADIO_EQ::m_my_data->main_iDomStatus->setObjectState(RADIO_EQ::m_config.name, STATE::ON);
48
27
}
28
29
void RADIO_SWITCH::off()
56
30
{
56
31
    main433MHz.sendCode(RADIO_EQ::m_config.offCode);
56
32
    m_state = STATE::OFF;
56
33
    RADIO_EQ::m_my_data->main_iDomStatus->setObjectState(RADIO_EQ::m_config.name,STATE::OFF);
56
34
}
35
36
void RADIO_SWITCH::onFor15sec()
4
37
{
4
38
    main433MHz.sendCode(RADIO_EQ::m_config.on15sec);
4
39
    m_state = STATE::WORKING;
4
40
}
41
42
void RADIO_SWITCH::onSunrise()
40
43
{
40
44
    if(m_sunrise == STATE::ON ){
4
45
        on();
4
46
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " ON due to sunrise");
4
47
    }
36
48
    else if(m_sunrise == STATE::OFF){
12
49
        off();
12
50
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " OFF due to sunrise");
12
51
    }
40
52
}
53
54
void RADIO_SWITCH::onSunset()
44
55
{
44
56
    if(m_sunset == STATE::ON ){
12
57
        on();
12
58
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " ON due to sunset");
12
59
    }
32
60
    else if(m_sunset == STATE::OFF){
4
61
        off();
4
62
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " OFF due to sunset");
4
63
    }
44
64
}
65
66
void RADIO_SWITCH::onLockHome()
28
67
{
28
68
    if (m_config.lock == "ON")
4
69
    {
4
70
        on();
4
71
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " ON due to 433MHz button pressed");
4
72
    }
24
73
    else if(m_config.lock == "OFF")
8
74
    {
8
75
        off();
8
76
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " OFF due to 433MHz button pressed");
8
77
    }
28
78
}
79
80
void RADIO_SWITCH::onUnlockHome()
28
81
{
28
82
    if (m_config.unlock == "ON")
8
83
    {
8
84
        on();
8
85
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " ON due to 433MHz button pressed");
8
86
    }
20
87
    else if (m_config.unlock == "OFF")
4
88
    {
4
89
        off();
4
90
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " OFF due to 433MHz button pressed");
4
91
    }
28
92
}
93
94
STATE RADIO_SWITCH::getState()
1.34k
95
{
1.34k
96
    return m_state;
1.34k
97
}
98
99
std::string RADIO_SWITCH::getName()
1.84k
100
{
1.84k
101
    return RADIO_EQ::m_config.name;
1.84k
102
}
103
104
std::string RADIO_SWITCH::getID()
440
105
{
440
106
    return RADIO_EQ::m_config.ID;
440
107
}
108
109
void RADIO_SWITCH::setCode(RADIO_EQ_CONFIG cfg)
2.66k
110
{
2.66k
111
    RADIO_EQ::m_config.onCode = cfg.onCode;
2.66k
112
    RADIO_EQ::m_config.offCode = cfg.offCode;
2.66k
113
    RADIO_EQ::m_config.on15sec = cfg.on15sec;
2.66k
114
    RADIO_EQ::m_config.type = cfg.type;
2.66k
115
    RADIO_EQ::m_config.lock = cfg.lock;
2.66k
116
    RADIO_EQ::m_config.unlock = cfg.unlock;
2.66k
117
    RADIO_EQ::m_config.name = cfg.name;
2.66k
118
2.66k
119
    if(cfg.sunset == "on"){
8
120
        m_sunset = STATE::ON;
8
121
    }
2.66k
122
    if(cfg.sunset == "off"){
4
123
        m_sunset = STATE::OFF;
4
124
    }
2.66k
125
    if(cfg.sunrise == "on"){
4
126
        m_sunrise = STATE::ON;
4
127
    }
2.66k
128
    if(cfg.sunrise == "off"){
8
129
        m_sunrise = STATE::OFF;
8
130
    }
2.66k
131
}
132
133
RADIO_EQ_CONTAINER::RADIO_EQ_CONTAINER(thread_data *my_data)
532
134
{
532
135
    puts("RADIO_EQ_CONTAINER::RADIO_EQ_CONTAINER()");
532
136
    this->my_data = my_data;
532
137
}
138
139
RADIO_EQ_CONTAINER::~RADIO_EQ_CONTAINER()
532
140
{
4.22k
141
    for(auto it = m_radioEqMap.begin(); it != m_radioEqMap.end(); ++it) {
3.69k
142
        delete it->second;
3.69k
143
    }
532
144
    puts("RADIO_EQ_CONTAINER::~RADIO_EQ_CONTAINER()");
532
145
}
146
147
void RADIO_EQ_CONTAINER::addRadioEq( RADIO_EQ_CONFIG cfg, RADIO_EQ_TYPE type)
3.71k
148
{
3.71k
149
    switch (type) {
2.65k
150
    case RADIO_EQ_TYPE::SWITCH:
2.65k
151
        m_radioEqMap.insert(std::make_pair(cfg.name, new RADIO_SWITCH(my_data, cfg, RADIO_EQ_TYPE::SWITCH) ) );
2.65k
152
        break;
532
153
    case RADIO_EQ_TYPE::BUTTON:
532
154
        m_radioEqMap.insert(std::make_pair(cfg.name, new RADIO_BUTTON(my_data, cfg, RADIO_EQ_TYPE::BUTTON) ) );
532
155
        break;
524
156
    case RADIO_EQ_TYPE::WEATHER_S:
524
157
        m_radioEqMap.insert(std::make_pair(cfg.name, new RADIO_WEATHER_STATION(my_data, cfg, RADIO_EQ_TYPE::WEATHER_S) ) );
524
158
        break;
4
159
    default:
4
160
        break;
3.71k
161
    }
3.71k
162
}
163
164
void RADIO_EQ_CONTAINER::addRadioEq(RADIO_EQ_CONFIG cfg, const std::string& type)
24
165
{
24
166
    RADIO_EQ_TYPE ret = RADIO_EQ_TYPE::NONE;
24
167
    if(type == "SWITCH") ret = RADIO_EQ_TYPE::SWITCH;
12
168
    else if(type == "BUTTON") ret = RADIO_EQ_TYPE::BUTTON;
8
169
    else if(type == "WEATHER") ret = RADIO_EQ_TYPE::WEATHER_S;
8
170
    else if(type == "PIR") ret = RADIO_EQ_TYPE::PIR;
4
171
    else if(type == "GATE") ret = RADIO_EQ_TYPE::GATE;
4
172
    else throw WRONG_FORMAT();
20
173
    std::cout << " id ma : " << cfg.ID << std::endl;
20
174
    std::stoi(cfg.ID); //check ID is number
20
175
    addRadioEq(cfg,ret);
20
176
}
177
178
void RADIO_EQ_CONTAINER::deleteRadioEq(const std::string& name)
16
179
{
16
180
    delete m_radioEqMap[name];
16
181
    m_radioEqMap.erase(name);
16
182
    saveConfig(my_data->server_settings->radio433MHzConfigFile);
16
183
}
184
185
RADIO_EQ* RADIO_EQ_CONTAINER::getEqPointer(std::string name)
2.90k
186
{
2.90k
187
    auto m = m_radioEqMap.find(name);
2.90k
188
    if (m != m_radioEqMap.end()){
2.90k
189
        return (m->second);
2.90k
190
    }
2.90k
191
    else
8
192
    {
8
193
        throw std::string("433MHz equipment not found "+name);
8
194
    }
2.90k
195
}
196
197
std::vector<RADIO_SWITCH*> RADIO_EQ_CONTAINER::getSwitchPointerVector()
344
198
{
344
199
    std::vector<RADIO_SWITCH*> switchVector;
344
200
2.42k
201
    for (auto it : m_radioEqMap){
2.42k
202
        if (it.second->getType() == RADIO_EQ_TYPE::SWITCH){
1.73k
203
            switchVector.push_back(static_cast<RADIO_SWITCH*>(it.second));
1.73k
204
        }
2.42k
205
    }
344
206
    return switchVector;
344
207
}
208
209
std::vector<RADIO_BUTTON *> RADIO_EQ_CONTAINER::getButtonPointerVector()
648
210
{
648
211
    std::vector<RADIO_BUTTON*> buttonVector;
648
212
4.54k
213
    for (auto it : m_radioEqMap){
4.54k
214
        if (it.second->getType() == RADIO_EQ_TYPE::BUTTON){
656
215
            buttonVector.push_back(static_cast<RADIO_BUTTON*>(it.second));
656
216
        }
4.54k
217
    }
648
218
    return buttonVector;
648
219
}
220
221
std::vector<RADIO_WEATHER_STATION *> RADIO_EQ_CONTAINER::getWeather_StationPtrVector()
112
222
{
112
223
    std::vector<RADIO_WEATHER_STATION*> weatherStVe;
792
224
    for (auto it : m_radioEqMap){
792
225
        if (it.second->getType() == RADIO_EQ_TYPE::WEATHER_S){
112
226
            weatherStVe.push_back(static_cast<RADIO_WEATHER_STATION*>(it.second));
112
227
        }
792
228
    }
112
229
    return weatherStVe;
112
230
}
231
232
std::string RADIO_EQ_CONTAINER::listAllName()
88
233
{
88
234
    std::string allName;
88
235
708
236
    for(auto it = m_radioEqMap.begin(); it != m_radioEqMap.end(); ++it) {
620
237
        allName.append(it->first);
620
238
        allName.append("\t ID: ");
620
239
        allName.append( it->second->getID() );
620
240
        allName.append("\t state: ");
620
241
        allName.append(stateToString(it->second->getState() ));
620
242
        allName.append("\n");
620
243
    }
88
244
88
245
    return allName;
88
246
}
247
248
bool RADIO_EQ_CONTAINER::nameExist(const std::string& name)
56
249
{
56
250
    bool exist = false;
56
251
    if(m_radioEqMap.find(name) != m_radioEqMap.end())
20
252
    {
20
253
        exist = true;
20
254
    }
56
255
    return exist;
56
256
}
257
258
void RADIO_EQ_CONTAINER::loadConfig(const std::string& filePath)
528
259
{
528
260
    std::ifstream myfile (filePath);
528
261
    if (myfile.is_open())
528
262
    {
528
263
        nlohmann::json j;
528
264
        myfile >> j;
528
265
528
266
        RADIO_EQ_CONFIG cfg;
528
267
528
268
        try
528
269
        {
528
270
            nlohmann::json switchJson = j.at("SWITCH");
3.16k
271
            for (nlohmann::json::iterator it = switchJson.begin(); it != switchJson.end(); ++it)
2.64k
272
            {
2.64k
273
                nlohmann::json switchJson = it.value();
2.64k
274
                cfg.name = switchJson.at("name").get<std::string>();
2.64k
275
                cfg.ID   = switchJson.at("id").get<std::string>();
2.64k
276
                cfg.offCode = switchJson.at("OFF").get<std::string>();
2.64k
277
                cfg.onCode  = switchJson.at("ON").get<std::string>();
2.64k
278
                cfg.on15sec = switchJson.at("on15sec").get<std::string>();
2.64k
279
                cfg.sunrise = switchJson.at("sunrise").get<std::string>();
2.64k
280
                cfg.sunset  = switchJson.at("sunset").get<std::string>();
2.64k
281
                cfg.lock    = switchJson.at("lock").get<std::string>();
2.64k
282
                cfg.unlock  = switchJson.at("unlock").get<std::string>();
2.64k
283
                cfg.type    = switchJson.at("type").get<std::string>();
2.64k
284
                addRadioEq(cfg,RADIO_EQ_TYPE::SWITCH);
2.64k
285
                dynamic_cast<RADIO_SWITCH*>(getEqPointer(cfg.name))->setCode(cfg);
2.64k
286
            }
528
287
        }
528
288
        catch(...)
0
289
        {
0
290
        log_file_mutex.mutex_lock();
0
291
        log_file_cout << DEBUG << "no SWITCH equipment in config" << std::endl;
0
292
        log_file_mutex.mutex_unlock();
0
293
        }
528
294
        try
528
295
        {
528
296
            nlohmann::json buttonJson = j.at("BUTTON");
1.05k
297
            for (nlohmann::json::iterator it = buttonJson.begin(); it != buttonJson.end(); ++it)
528
298
            {
528
299
                nlohmann::json buttonJson = it.value();
528
300
                cfg.name = buttonJson.at("name").get<std::string>();
528
301
                cfg.ID   = buttonJson.at("id").get<std::string>();
528
302
                cfg.offCode = buttonJson.at("OFF").get<std::string>();
528
303
                cfg.onCode  = buttonJson.at("ON").get<std::string>();
528
304
                cfg.type    = buttonJson.at("type").get<std::string>();
528
305
                addRadioEq(cfg,RADIO_EQ_TYPE::BUTTON);
528
306
            }
528
307
        }
528
308
        catch(...)
0
309
        {
0
310
            log_file_mutex.mutex_lock();
0
311
            log_file_cout << DEBUG << "no BUTTONs equipment in config" << std::endl;
0
312
            log_file_mutex.mutex_unlock();
0
313
#ifdef BT_TEST
0
314
            std::cout << "no BUTTONs equipment in config" <<std::endl;
0
315
#endif
0
316
        }
528
317
528
318
        try
528
319
        {
528
320
            nlohmann::json weatherJson= j.at("WEATHER");
1.05k
321
            for (nlohmann::json::iterator it = weatherJson.begin(); it != weatherJson.end(); ++it)
524
322
            {
524
323
                nlohmann::json weatherJson = it.value();
524
324
                cfg.name = weatherJson.at("name").get<std::string>();
524
325
                cfg.ID   = weatherJson.at("id").get<std::string>();
524
326
                cfg.type    = weatherJson.at("type").get<std::string>();
524
327
                addRadioEq(cfg,RADIO_EQ_TYPE::WEATHER_S);
524
328
            }
528
329
        }
528
330
        catch(...)
4
331
        {
4
332
            log_file_mutex.mutex_lock();
4
333
            log_file_cout << DEBUG << "no WEATHER STAIONs equipment in config" << std::endl;
4
334
            log_file_mutex.mutex_unlock();
4
335
#ifdef BT_TEST
4
336
            std::cout << "no WEATHER STAIONs equipment in config" <<std::endl;
4
337
#endif
4
338
        }
528
339
528
340
        myfile.close();
528
341
    }
0
342
    else std::cout << "Unable to open file";
528
343
}
344
345
void RADIO_EQ_CONTAINER::saveConfig(const std::string& filePath)
40
346
{
40
347
    nlohmann::json switchJson;
40
348
    nlohmann::json buttonJson;
40
349
    nlohmann::json weatherJson;
40
350
40
351
    std::vector<RADIO_SWITCH*> vSwitch = getSwitchPointerVector();
40
352
    for(auto s : vSwitch)
204
353
    {
204
354
        switchJson[s->getName()] = s->m_config.getJson();
204
355
    }
40
356
40
357
    std::vector<RADIO_BUTTON*> vButton = getButtonPointerVector();
40
358
    for (auto s : vButton)
44
359
    {
44
360
        buttonJson[s->getName()] = s->m_config.getJson();
44
361
    }
40
362
40
363
    std::vector<RADIO_WEATHER_STATION *> vWeather = getWeather_StationPtrVector();
40
364
    for(auto s : vWeather)
40
365
    {
40
366
        weatherJson[s->getName()] = s->m_config.getJson();
40
367
    }
40
368
40
369
    m_configJson["SWITCH"] = switchJson;
40
370
    m_configJson["BUTTON"] = buttonJson;
40
371
    m_configJson["WEATHER"] = weatherJson;
40
372
    // write prettified JSON to another file
40
373
    std::ofstream o(filePath);
40
374
    o << std::setw(4) << m_configJson << std::endl;
40
375
}
376
377
RADIO_EQ::RADIO_EQ()
3.71k
378
{
3.71k
379
    this->m_my_data = std::nullptr_t();
3.71k
380
    puts("RADIO_EQ::RADIO_EQ()");
3.71k
381
}
382
383
RADIO_EQ::~RADIO_EQ()
3.71k
384
{
3.71k
385
    puts("RADIO_EQ::~RADIO_EQ()");
3.71k
386
}
387
388
RADIO_EQ_TYPE RADIO_EQ::getType()
7.76k
389
{
7.76k
390
    return m_type;
7.76k
391
}
392
393
RADIO_WEATHER_STATION::RADIO_WEATHER_STATION(thread_data *my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type)
524
394
{
524
395
    puts("RADIO_WEATHER_STATION::RADIO_WEATHER_STATION()");
524
396
    RADIO_EQ::m_my_data = my_data;
524
397
    RADIO_EQ::m_type = type;
524
398
    RADIO_EQ::m_config = cfg;
524
399
}
400
401
RADIO_WEATHER_STATION::~RADIO_WEATHER_STATION()
524
402
{
524
403
    puts("RADIO_WEATHER_STATION::~RADIO_WEATHER_STATION()");
524
404
}
405
406
STATE RADIO_WEATHER_STATION::getState()
88
407
{
88
408
    return m_state;
88
409
}
410
411
std::string RADIO_WEATHER_STATION::getName()
40
412
{
40
413
    return RADIO_EQ::m_config.name;
40
414
}
415
416
std::string RADIO_WEATHER_STATION::getID()
136
417
{
136
418
    return RADIO_EQ::m_config.ID;
136
419
}
/home/pi/programowanie/iDom_server_OOP/src/RADIO_433_eq/radio_433_eq.h
1
#ifndef RADIO_SWITCH_H
2
#define RADIO_SWITCH_H
3
#include <gtest/gtest.h>
4
#include <gmock/gmock.h>
5
#include <map>
6
#include "../iDomStatus/idomstatus.h"
7
#include "../433MHz/RFLink/rflinkhandler.h"
8
9
#include "../433MHz/rc_433mhz.h"
10
#include "json.hpp"
11
12
struct WEATHER_STRUCT{
13
private:
14
    unsigned long int m_counter = 0;
15
protected:
16
    unsigned int m_humidity = 0;
17
    double m_temperature = 0.0;
18
    unsigned int m_barometricPressure = 0;
19
public:
20
    unsigned int getHumidity(){ return m_humidity; }
21
    double getTemperature(){ return m_temperature; }
22
    unsigned int getBarometricPressure(){ return m_barometricPressure; }
23
    std::string getDataString(){
24
        return "data: "+std::to_string(m_counter)+"\n"+"Humidity=" + std::to_string(getHumidity()) +"%\n"+
25
                "temperature= " + to_string_with_precision(getTemperature()) + "c\n"+
26
                "Pressure= " + std::to_string(getBarometricPressure())+ "kPa\n";
27
    }
28
29
    void putData(std::string data){
30
        std::string tempStr;
31
        int t = 0;
32
        ++m_counter;
33
        try{
34
            m_humidity = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "HUM") );
35
        }
36
        catch (...){ }
37
        try{
38
            m_barometricPressure = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "BARO") );
39
        }
40
        catch (...){ }
41
        try{
42
            tempStr = RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "TEMP");
43
            std::stringstream ss;
44
            ss << std::hex << tempStr.substr(tempStr.size()-3,tempStr.size());
45
            ss >> t;
46
            m_temperature = t / 10.0;
47
            if(tempStr.at(0) == '8'){
48
                m_temperature *= -1.0;
49
            }
50
        }
51
        catch (...){ }
52
        //std::cout << "DUPA: "<<data<<" temp=" << m_temperature<< " hum="<<m_humidity<< std::endl;
53
    }
54
};
55
56
enum class RADIO_EQ_TYPE{
57
    SWITCH = 1,
58
    PIR,
59
    GATE,
60
    BUTTON,
61
    WEATHER_S,
62
    NONE
63
};
64
struct RADIO_EQ_CONFIG{
65
    std::string name = "NULL";
66
    std::string ID   = "NULL";
67
    std::string type = "NULL";
68
    std::string onCode  = "NULL";
69
    std::string offCode = "NULL";
70
    std::string on15sec = "NULL";
71
    std::string sunrise = "NULL";
72
    std::string sunset  = "NULL";
73
    std::string lock   = "NULL";
74
    std::string unlock = "NULL";
75
    void set(std::string type,
76
             std::string name,
77
             std::string ID,
78
             std::string onCode = "null",
79
             std::string offCode = "null",
80
             std::string on15sec = "null",
81
             std::string sunrise = "null",
82
             std::string sunset = "null",
83
             std::string lock = "null",
84
             std::string unlock = "null"){
85
        this->name = name;
86
        this->ID   = ID;
87
        this->type = type;
88
        this->onCode  = onCode;
89
        this->offCode = offCode;
90
        this->on15sec = on15sec;
91
        this->sunrise = sunrise;
92
        this->sunset  = sunset;
93
        this->lock   = lock;
94
        this->unlock = unlock;
95
    }
96
288
97
    nlohmann::json getJson(){
288
98
        nlohmann::json jj;
288
99
        jj["name"]  = name;
288
100
        jj["id"]    = ID;
288
101
        jj["type"]  = type;
288
102
        jj["ON"]    = onCode;
288
103
        jj["OFF"]   = offCode;
288
104
        jj["on15sec"] = on15sec;
288
105
        jj["sunrise"] = sunrise;
288
106
        jj["sunset"]  = sunset;
288
107
        jj["lock"]   = lock;
288
108
        jj["unlock"] = unlock;
288
109
        return jj;
288
110
    }
111
};
112
113
class RADIO_EQ{
114
public:
115
    RADIO_EQ();
116
    virtual ~RADIO_EQ();
117
    virtual STATE getState() = 0;
118
    virtual std::string getName() = 0;
119
    virtual std::string getID() = 0;
120
    virtual RADIO_EQ_TYPE getType();
121
protected:
122
    thread_data *m_my_data;
123
    RADIO_EQ_TYPE m_type;
124
public:
125
    RADIO_EQ_CONFIG m_config;
126
};
127
class RADIO_WEATHER_STATION: public RADIO_EQ
128
{
129
    STATE m_state = STATE::UNDEFINE;
130
131
public:
132
    RADIO_WEATHER_STATION(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
133
    ~RADIO_WEATHER_STATION();
134
    STATE getState();
135
    std::string getName();
136
    std::string getID();
137
    // data
138
    WEATHER_STRUCT data;
139
};
140
class RADIO_BUTTON: public RADIO_EQ
141
{
142
    STATE m_state = STATE::UNDEFINE;
143
144
public:
145
    RADIO_BUTTON(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
146
    ~RADIO_BUTTON();
147
    STATE getState();
148
    void setState(STATE s);
149
    std::string getName();
150
    std::string getID();
151
};
152
153
class RADIO_SWITCH: public RADIO_EQ
154
{
155
#ifdef BT_TEST
156
public:
157
#endif
158
    RC_433MHz main433MHz;
159
    STATE m_state = STATE::UNDEFINE;
160
public:
161
    RADIO_SWITCH(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
162
    ~RADIO_SWITCH();
163
    void on();
164
    void off();
165
    void onFor15sec();
166
    void onSunrise();
167
    void onSunset();
168
    void onLockHome();
169
    void onUnlockHome();
170
    STATE getState();
171
    std::string getName();
172
    std::string getID();
173
    void setCode(RADIO_EQ_CONFIG cfg);
174
    STATE m_sunrise = STATE::UNDEFINE;
175
    STATE m_sunset  = STATE::UNDEFINE;
176
};
177
178
class RADIO_EQ_CONTAINER
179
{
180
    std::map <std::string, RADIO_EQ* > m_radioEqMap;
181
    thread_data * my_data;
182
    nlohmann::json m_configJson;
183
public:
184
    RADIO_EQ_CONTAINER(thread_data * my_data);
185
    virtual ~RADIO_EQ_CONTAINER();
186
    void addRadioEq(RADIO_EQ_CONFIG cfg, RADIO_EQ_TYPE type);
187
    void addRadioEq(RADIO_EQ_CONFIG cfg, const std::string& type);
188
    void deleteRadioEq(const std::string &name);
189
    virtual RADIO_EQ* getEqPointer(std::string name);
190
    std::vector<RADIO_SWITCH*> getSwitchPointerVector();
191
    std::vector<RADIO_BUTTON*> getButtonPointerVector();
192
    std::vector<RADIO_WEATHER_STATION *> getWeather_StationPtrVector();
193
    std::string listAllName();
194
    bool nameExist(const std::string &name);
195
    void loadConfig(const std::string &filePath);
196
    void saveConfig(const std::string &filePath);
197
};
198
199
class RADIO_EQ_CONTAINER_STUB : public RADIO_EQ_CONTAINER
200
{
201
    thread_data * k;
202
public:
203
    RADIO_EQ_CONTAINER_STUB(thread_data * k):RADIO_EQ_CONTAINER(k){this->k = k;}
204
205
    virtual ~RADIO_EQ_CONTAINER_STUB(){puts("~RADIO_EQ_CONTAINER_STUB()");}
206
    MOCK_METHOD1(getEqPointer, RADIO_EQ*(std::string name));
207
};
208
209
#endif // RADIO_SWITCH_H
/home/pi/programowanie/iDom_server_OOP/src/RADIO_433_eq/radio_button.cpp
1
#include "radio_433_eq.h"
2
/*
3
 * Najpierw możliwe do uzyskania funkcje załączania
4
5
    Załączenie chwilowe (momentary) - przekaźnik jest załączony tak długo jak długo naciskany jest klawisz pilota - nadawany kod
6
    Przełącznik (toggle) - przekaźnik jest załączany /wyłączany przy kolejnych naciśnięciach tego samego klawisza - nadajemy ten sam kod
7
    Włącz/wyłącz (latched) - przekaźnik jest załączany jednym kodem a wyłączany innym
8
    Włącznik czasowy 5 sek - po naciśnięciu pilota następuje załączenie przekaźnika na czas 5 sek
9
    Włącznik czasowy 10 sek - załączenie na czas 10 sek
10
    Włącznik czasowy 15 sek - załączenie na czas 15 sek
11
12
Programowanie
13
Niby opisane jest to na stronach dostawców - ale nie do końca - więc pełen opis programowania. Zalecane rozpoczęcie od punktu 8 - KASOWANIE
14
15
    Załączenie chwilowe (momentary) - naciskamy 1x przycisk programowania (potwierdzenie naciśnięcia krótkim błyskiem LED). LED po chwili włącza się na stałe na 8-10 sek. W tym czasie układ gotowy jest na przyjęcie nowego kodu. Wysłany kod zapamiętany jest w pamięci a potwierdzeniem tego jest podwójne "mrugnięcie" LEDa. LED gaśnie . Koniec procedury.
16
    Przełącznik (toggle) - naciskamy 2 x przycisk programowania. Dalej jak w pkt. 1
17
    Włącz/wyłącz (latched) - naciskamy 3 x przycisk programowania (potwierdzenie naciśnięcia krótkim błyskiem LED). LED po chwili włącza się na stałe na 8-10 sek. W tym czasie układ gotowy jest na przyjęcie nowego kodu. Wysłany kod zapamiętany jest w pamięci a potwierdzeniem tego jest podwójne "mrugnięcie" LEDa. LED pozostaje włączony Układ czeka na odbiór drugiego kodu. Po jego wysłaniu jest znowu podwójne "mrugnięcie" LEDa. LED gaśnie. Koniec procedury.
18
    Włącznik czasowy 5 sek - naciskamy 4 x przycisk programowania. Dalej jak w pkt. 1
19
    Włącznik czasowy 10 sek - naciskamy 5 x przycisk programowania. Dalej jak w pkt. 1
20
    Włącznik czasowy 15 sek - naciskamy 6 x przycisk programowania. Dalej jak w pkt. 1
21
    Włącznik czasowy 15 sek - naciskamy 7 x przycisk programowania. Dalej jak w pkt. 1
22
     KASOWANIE - usuwanie z pamięci wszystkich kodów. Nacisnąć 8 x przycisk. Każde naciśniecie sygnalizowane jest błyśnięciem. Po 8 naciśnięciu następują trzy mignięcia i pamięć kodów jest wyzerowana. Można też skasować pamięć naciskając przycisk raz przez ok 8 sek . Po puszczeniu przycisku LED zapali się na ok 3-4 sek i zgaśnie. Efekt działania ten sam.
23
24
Wszystkie te funkcje działają równolegle bo układ może zapamiętać do 50 kodów! Dodatkowo w trybie włącznika czasowego można skrócić czas załączenia poprzez wysłanie kodu WYŁĄCZ z wcześniej ustawionej funkcji latched.
25
 */
26
RADIO_BUTTON::RADIO_BUTTON(thread_data *my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type)
532
27
{
532
28
    puts("RADIO_BUTTON::RADIO_BUTTON()");
532
29
    RADIO_EQ::m_my_data = my_data;
532
30
    RADIO_EQ::m_type = type;
532
31
    RADIO_EQ::m_config = cfg;
532
32
}
33
34
RADIO_BUTTON::~RADIO_BUTTON()
532
35
{
532
36
    puts("RADIO_BUTTON::~RADIO_BUTTON()");
532
37
}
38
39
STATE RADIO_BUTTON::getState()
92
40
{
92
41
    return m_state;
92
42
}
43
44
void RADIO_BUTTON::setState(STATE s)
24
45
{
24
46
    m_state = s;
24
47
}
48
49
std::string RADIO_BUTTON::getName()
48
50
{
48
51
    return RADIO_EQ::m_config.name;
48
52
}
53
54
std::string RADIO_BUTTON::getID()
152
55
{
152
56
    return RADIO_EQ::m_config.ID;
152
57
}
/home/pi/programowanie/iDom_server_OOP/src/RADIO_433_eq/test/../../iDomTools/test/../../RADIO_433_eq/radio_433_eq.h
1
#ifndef RADIO_SWITCH_H
2
#define RADIO_SWITCH_H
3
#include <gtest/gtest.h>
4
#include <gmock/gmock.h>
5
#include <map>
6
#include "../iDomStatus/idomstatus.h"
7
#include "../433MHz/RFLink/rflinkhandler.h"
8
9
#include "../433MHz/rc_433mhz.h"
10
#include "json.hpp"
11
12
struct WEATHER_STRUCT{
13
private:
14
    unsigned long int m_counter = 0;
15
protected:
16
    unsigned int m_humidity = 0;
17
    double m_temperature = 0.0;
18
    unsigned int m_barometricPressure = 0;
19
public:
16
20
    unsigned int getHumidity(){ return m_humidity; }
28
21
    double getTemperature(){ return m_temperature; }
12
22
    unsigned int getBarometricPressure(){ return m_barometricPressure; }
8
23
    std::string getDataString(){
8
24
        return "data: "+std::to_string(m_counter)+"\n"+"Humidity=" + std::to_string(getHumidity()) +"%\n"+
8
25
                "temperature= " + to_string_with_precision(getTemperature()) + "c\n"+
8
26
                "Pressure= " + std::to_string(getBarometricPressure())+ "kPa\n";
8
27
    }
28
20
29
    void putData(std::string data){
20
30
        std::string tempStr;
20
31
        int t = 0;
20
32
        ++m_counter;
20
33
        try{
20
34
            m_humidity = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "HUM") );
20
35
        }
16
36
        catch (...){ }
20
37
        try{
20
38
            m_barometricPressure = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "BARO") );
20
39
        }
16
40
        catch (...){ }
20
41
        try{
20
42
            tempStr = RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "TEMP");
20
43
            std::stringstream ss;
20
44
            ss << std::hex << tempStr.substr(tempStr.size()-3,tempStr.size());
20
45
            ss >> t;
20
46
            m_temperature = t / 10.0;
20
47
            if(tempStr.at(0) == '8'){
8
48
                m_temperature *= -1.0;
8
49
            }
20
50
        }
4
51
        catch (...){ }
20
52
        //std::cout << "DUPA: "<<data<<" temp=" << m_temperature<< " hum="<<m_humidity<< std::endl;
20
53
    }
54
};
55
56
enum class RADIO_EQ_TYPE{
57
    SWITCH = 1,
58
    PIR,
59
    GATE,
60
    BUTTON,
61
    WEATHER_S,
62
    NONE
63
};
64
struct RADIO_EQ_CONFIG{
65
    std::string name = "NULL";
66
    std::string ID   = "NULL";
67
    std::string type = "NULL";
68
    std::string onCode  = "NULL";
69
    std::string offCode = "NULL";
70
    std::string on15sec = "NULL";
71
    std::string sunrise = "NULL";
72
    std::string sunset  = "NULL";
73
    std::string lock   = "NULL";
74
    std::string unlock = "NULL";
75
    void set(std::string type,
76
             std::string name,
77
             std::string ID,
78
             std::string onCode = "null",
79
             std::string offCode = "null",
80
             std::string on15sec = "null",
81
             std::string sunrise = "null",
82
             std::string sunset = "null",
83
             std::string lock = "null",
84
             std::string unlock = "null"){
85
        this->name = name;
86
        this->ID   = ID;
87
        this->type = type;
88
        this->onCode  = onCode;
89
        this->offCode = offCode;
90
        this->on15sec = on15sec;
91
        this->sunrise = sunrise;
92
        this->sunset  = sunset;
93
        this->lock   = lock;
94
        this->unlock = unlock;
95
    }
96
97
    nlohmann::json getJson(){
98
        nlohmann::json jj;
99
        jj["name"]  = name;
100
        jj["id"]    = ID;
101
        jj["type"]  = type;
102
        jj["ON"]    = onCode;
103
        jj["OFF"]   = offCode;
104
        jj["on15sec"] = on15sec;
105
        jj["sunrise"] = sunrise;
106
        jj["sunset"]  = sunset;
107
        jj["lock"]   = lock;
108
        jj["unlock"] = unlock;
109
        return jj;
110
    }
111
};
112
113
class RADIO_EQ{
114
public:
115
    RADIO_EQ();
116
    virtual ~RADIO_EQ();
117
    virtual STATE getState() = 0;
118
    virtual std::string getName() = 0;
119
    virtual std::string getID() = 0;
120
    virtual RADIO_EQ_TYPE getType();
121
protected:
122
    thread_data *m_my_data;
123
    RADIO_EQ_TYPE m_type;
124
public:
125
    RADIO_EQ_CONFIG m_config;
126
};
127
class RADIO_WEATHER_STATION: public RADIO_EQ
128
{
129
    STATE m_state = STATE::UNDEFINE;
130
131
public:
132
    RADIO_WEATHER_STATION(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
133
    ~RADIO_WEATHER_STATION();
134
    STATE getState();
135
    std::string getName();
136
    std::string getID();
137
    // data
138
    WEATHER_STRUCT data;
139
};
140
class RADIO_BUTTON: public RADIO_EQ
141
{
142
    STATE m_state = STATE::UNDEFINE;
143
144
public:
145
    RADIO_BUTTON(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
146
    ~RADIO_BUTTON();
147
    STATE getState();
148
    void setState(STATE s);
149
    std::string getName();
150
    std::string getID();
151
};
152
153
class RADIO_SWITCH: public RADIO_EQ
154
{
155
#ifdef BT_TEST
156
public:
157
#endif
158
    RC_433MHz main433MHz;
159
    STATE m_state = STATE::UNDEFINE;
160
public:
161
    RADIO_SWITCH(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
162
    ~RADIO_SWITCH();
163
    void on();
164
    void off();
165
    void onFor15sec();
166
    void onSunrise();
167
    void onSunset();
168
    void onLockHome();
169
    void onUnlockHome();
170
    STATE getState();
171
    std::string getName();
172
    std::string getID();
173
    void setCode(RADIO_EQ_CONFIG cfg);
174
    STATE m_sunrise = STATE::UNDEFINE;
175
    STATE m_sunset  = STATE::UNDEFINE;
176
};
177
178
class RADIO_EQ_CONTAINER
179
{
180
    std::map <std::string, RADIO_EQ* > m_radioEqMap;
181
    thread_data * my_data;
182
    nlohmann::json m_configJson;
183
public:
184
    RADIO_EQ_CONTAINER(thread_data * my_data);
185
    virtual ~RADIO_EQ_CONTAINER();
186
    void addRadioEq(RADIO_EQ_CONFIG cfg, RADIO_EQ_TYPE type);
187
    void addRadioEq(RADIO_EQ_CONFIG cfg, const std::string& type);
188
    void deleteRadioEq(const std::string &name);
189
    virtual RADIO_EQ* getEqPointer(std::string name);
190
    std::vector<RADIO_SWITCH*> getSwitchPointerVector();
191
    std::vector<RADIO_BUTTON*> getButtonPointerVector();
192
    std::vector<RADIO_WEATHER_STATION *> getWeather_StationPtrVector();
193
    std::string listAllName();
194
    bool nameExist(const std::string &name);
195
    void loadConfig(const std::string &filePath);
196
    void saveConfig(const std::string &filePath);
197
};
198
199
class RADIO_EQ_CONTAINER_STUB : public RADIO_EQ_CONTAINER
200
{
201
    thread_data * k;
202
public:
203
    RADIO_EQ_CONTAINER_STUB(thread_data * k):RADIO_EQ_CONTAINER(k){this->k = k;}
204
205
    virtual ~RADIO_EQ_CONTAINER_STUB(){puts("~RADIO_EQ_CONTAINER_STUB()");}
206
    MOCK_METHOD1(getEqPointer, RADIO_EQ*(std::string name));
207
};
208
209
#endif // RADIO_SWITCH_H
/home/pi/programowanie/iDom_server_OOP/src/RADIO_433_eq/test/radio_433_test.cpp
1
#include <gtest/gtest.h>
2
#include <gmock/gmock.h>
3
#include "../radio_433_eq.h"
4
#include "../../iDomTools/test/iDomTools_fixture.h"
5
6
RC_433MHz::RC_433MHz(thread_data *test_my_data)
2.65k
7
{
2.65k
8
    this->m_my_data = test_my_data;
2.65k
9
}
10
void RC_433MHz::sendCode(const std::string& code)
108
11
{
108
12
    std::cout << "sendCode(): " << code << std::endl;
108
13
}
14
15
class Switch_Class_fixture : public iDomTOOLS_ClassTest
16
{
17
18
};
19
TEST_F(Switch_Class_fixture, getSwitchPointerVector)
4
20
{
4
21
    auto v = test_rec.getSwitchPointerVector();
4
22
    EXPECT_EQ(v.size(),5);
4
23
}
24
25
TEST_F(Switch_Class_fixture, getButtonPointerVector)
4
26
{
4
27
    auto v = test_rec.getButtonPointerVector();
4
28
    EXPECT_EQ(v.size(),1);
4
29
}
30
31
TEST_F(Switch_Class_fixture, switch_alarm_on)
4
32
{
4
33
    RADIO_SWITCH* ptr = dynamic_cast<RADIO_SWITCH*>(test_rec.getEqPointer("ALARM"));
4
34
4
35
    EXPECT_EQ(ptr->getType(),RADIO_EQ_TYPE::SWITCH);
4
36
    puts("radio switch type");
4
37
    EXPECT_EQ(ptr->getState(),STATE::UNDEFINE);
4
38
    puts("radio switch state");
4
39
    ptr->on();
4
40
    EXPECT_EQ(ptr->getState(),STATE::ON);
4
41
    ptr->off();
4
42
    EXPECT_EQ(ptr->getState(),STATE::OFF);
4
43
    ptr->onSunset();
4
44
    EXPECT_EQ(ptr->getState(),STATE::OFF);
4
45
}
46
47
TEST_F(Switch_Class_fixture, weatherStruct)
4
48
{
4
49
    WEATHER_STRUCT test_WS;
12
50
    EXPECT_DOUBLE_EQ(0.0, test_WS.getTemperature()) << "Tempertura zla";
4
51
4
52
    test_WS.putData("20;03;LaCrosse;ID=0506;TEMP=0137;");
12
53
    EXPECT_DOUBLE_EQ(31.1, test_WS.getTemperature()) << "Tempertura zla";
4
54
4
55
    test_WS.putData("20;03;LaCrosse;ID=0506;TEMP=8130;BARO=999;");
12
56
    EXPECT_DOUBLE_EQ(-30.4, test_WS.getTemperature()) << "Tempertura zla";
4
57
12
58
    EXPECT_EQ(999, test_WS.getBarometricPressure()) << "zle cisneinie";
4
59
4
60
    std::string retString = test_WS.getDataString();
4
61
    EXPECT_THAT(retString, testing::HasSubstr("Pressure= 999kPa"));
4
62
}
63
64
TEST_F(Switch_Class_fixture, read_write_config_json)
4
65
{
4
66
    auto v = test_rec.getSwitchPointerVector();
4
67
    EXPECT_EQ(v.size(),5);
4
68
    test_rec.saveConfig(test_server_set.radio433MHzConfigFile);
4
69
    v = test_rec.getSwitchPointerVector();
4
70
    EXPECT_EQ(v.size(),5);
4
71
}
72
TEST_F(Switch_Class_fixture, addUnexistsRadioEq)
4
73
{
4
74
    RADIO_EQ_CONFIG tCfg;
4
75
    tCfg.name = "cyniu";
4
76
    tCfg.ID = "8899";
4
77
    std::string _name = tCfg.name;
4
78
    EXPECT_FALSE(test_rec.nameExist(_name));
4
79
    test_rec.addRadioEq(tCfg, "PIR");
4
80
    EXPECT_FALSE(test_rec.nameExist(_name));
4
81
}
82
83
TEST_F(Switch_Class_fixture, add_and_erase_switch)
4
84
{
4
85
    RADIO_EQ_CONFIG tCfg;
4
86
    tCfg.name = "test";
4
87
    test_rec.addRadioEq(tCfg, RADIO_EQ_TYPE::SWITCH);
4
88
    auto v = test_rec.getSwitchPointerVector();
4
89
    EXPECT_EQ(v.size(),6);
4
90
    test_rec.saveConfig(test_server_set.radio433MHzConfigFile);
4
91
    v = test_rec.getSwitchPointerVector();
4
92
    EXPECT_EQ(v.size(),6);
4
93
4
94
    ///////delete
4
95
    test_rec.deleteRadioEq(tCfg.name);
4
96
    v = test_rec.getSwitchPointerVector();
4
97
    EXPECT_EQ(v.size(),5);
4
98
    test_rec.saveConfig(test_server_set.radio433MHzConfigFile);
4
99
    v = test_rec.getSwitchPointerVector();
4
100
    EXPECT_EQ(v.size(),5);
4
101
}
102
103
TEST_F(Switch_Class_fixture, loadConfig)
4
104
{
4
105
    RADIO_EQ_CONTAINER test_rec(&test_my_data);
4
106
    test_rec.loadConfig("/mnt/ramdisk/433_eq_conf_fake.json");
4
107
4
108
    EXPECT_FALSE(test_rec.nameExist("firstt"));
4
109
    EXPECT_TRUE(test_rec.nameExist("locker"));
4
110
}
111
112
TEST_F(Switch_Class_fixture, getUnexistPtr)
4
113
{
4
114
    EXPECT_THROW(test_rec.getEqPointer("kokos"),std::string);
4
115
}
116
117
TEST_F(Switch_Class_fixture, onLock_onUnlock_HOME)
4
118
{
4
119
    RADIO_EQ_CONFIG tCfg;
4
120
    tCfg.name = "cyniu";
4
121
    tCfg.ID = "8899";
4
122
    tCfg.lock =  "ON";
4
123
4
124
    auto testRadioS = static_cast<RADIO_SWITCH*>(test_rec.getEqPointer("C"));
4
125
    testRadioS->setCode(tCfg);
4
126
    testRadioS->onLockHome();
4
127
    std::string eventStr = test_my_data.myEventHandler.run("iDom")->getEvent();
4
128
    EXPECT_THAT(eventStr, testing::HasSubstr("cyniu ON due to 433MHz button pressed"));
4
129
4
130
    tCfg.lock =  "OFF";
4
131
    testRadioS->setCode(tCfg);
4
132
    testRadioS->onLockHome();
4
133
    eventStr = test_my_data.myEventHandler.run("iDom")->getEvent();
4
134
    EXPECT_THAT(eventStr, testing::HasSubstr("cyniu OFF due to 433MHz button pressed"));
4
135
4
136
    ////////////////////// unlock
4
137
    tCfg.unlock =  "ON";
4
138
4
139
    testRadioS->setCode(tCfg);
4
140
    testRadioS->onUnlockHome();
4
141
     eventStr = test_my_data.myEventHandler.run("iDom")->getEvent();
4
142
    EXPECT_THAT(eventStr, testing::HasSubstr("cyniu ON due to 433MHz button pressed"));
4
143
4
144
    tCfg.unlock =  "OFF";
4
145
    testRadioS->setCode(tCfg);
4
146
    testRadioS->onUnlockHome();
4
147
    eventStr = test_my_data.myEventHandler.run("iDom")->getEvent();
4
148
    EXPECT_THAT(eventStr, testing::HasSubstr("cyniu OFF due to 433MHz button pressed"));
4
149
}
/home/pi/programowanie/iDom_server_OOP/src/THERMOMETER_CONTAINER/test/thermometer_container_BT.cpp
1
#include <gtest/gtest.h>
2
#include <gmock/gmock.h>
3
#include "../../iDomTools/test/iDomTools_fixture.h"
4
#include "../thermometer_container.h"
5
6
class Thermometer_container_fixture :  public ::testing::Test //public iDomTOOLS_ClassTest
7
{
8
public:
9
    THERMOMETER_CONTAINER testThermo;
10
    std::string termoName = "test_thermometer";
11
    std::vector<std::string> v;
12
13
    void SetUp() final
16
14
    {
16
15
        std::vector<std::string> v = {"10.2","11.22"};
16
16
        testThermo.add("inside");
16
17
        testThermo.add("outside");
16
18
        testThermo.updateAll(&v);
16
19
        v = {"20.2","21.22"};
16
20
        testThermo.updateAll(&v);
16
21
        std::cout << "temepratura inside" << testThermo.getTemp("inside") << std::endl;
16
22
        std::cout << "temepratura outside" << testThermo.getTemp("outside") << std::endl;
16
23
        testThermo.updateStats("inside");
16
24
        testThermo.updateStats("outside");
16
25
        std::cout << "rozmiar mapy termoetrow: " << testThermo.sizeOf() << std::endl;
16
26
        testThermo.showAll();
16
27
        puts("SetUp() Thermometer_container_fixture");
16
28
        puts("--------------------------------------");
16
29
    }
30
};
31
TEST_F(Thermometer_container_fixture, returnUnexistPTR)
4
32
{
4
33
    EXPECT_THROW(testThermo.returnThermometerPtr("fake"),std::string);
4
34
}
35
36
TEST_F(Thermometer_container_fixture, getStatsByName)
4
37
{
4
38
    std::string returnedStr = testThermo.getStatsByName("inside");
4
39
    std::cout << "zwrocono " << returnedStr << std::endl;
4
40
    EXPECT_THAT(returnedStr, testing::HasSubstr("min: 20.2"));
4
41
    EXPECT_THAT(returnedStr, testing::HasSubstr("max: 20.2"));
4
42
}
43
44
TEST_F(Thermometer_container_fixture, getLast2)
4
45
{
4
46
    std::cout << "rozmiar mapy termoetrow: " << testThermo.sizeOf() << std::endl;
4
47
    testThermo.updateStats("inside");
4
48
    testThermo.updateStats("outside");
4
49
    testThermo.showAll();
4
50
    v = {"44.4","45.45"};
4
51
    testThermo.updateAll(&v);
4
52
    testThermo.updateStats("inside");
4
53
    testThermo.updateStats("outside");
4
54
    std::string returnedStr = testThermo.getStatsByName("inside");
4
55
    std::cout << "zwrocono " << returnedStr <<"||"<< std::endl;
4
56
    auto v = testThermo.getLast2("inside");
4
57
    EXPECT_EQ(v.first, 20.2);
4
58
    EXPECT_EQ(v.second, 44.4);
4
59
}
60
61
TEST_F(Thermometer_container_fixture, isMoreDiff)
4
62
{
4
63
    std::cout << "rozmiar mapy termoetrow: " << testThermo.sizeOf() << std::endl;
4
64
    testThermo.updateStats("inside");
4
65
    testThermo.updateStats("outside");
4
66
    testThermo.showAll();
4
67
    v = {"24.4","45.45"};
4
68
    testThermo.updateAll(&v);
4
69
    testThermo.updateStats("inside");
4
70
    testThermo.updateStats("outside");
4
71
    EXPECT_FALSE(testThermo.isMoreDiff("inside",15.5));
4
72
    EXPECT_TRUE(testThermo.isMoreDiff("outside",15.5));
4
73
}
/home/pi/programowanie/iDom_server_OOP/src/THERMOMETER_CONTAINER/thermometer_container.cpp
1
#include "thermometer_container.h"
2
3
THERMOMETER *THERMOMETER_CONTAINER::returnThermometerPtr(const std::string& name)
1.17k
4
{
1.17k
5
    auto m = thermoMap.find(name);
1.17k
6
    if (m != thermoMap.end())
1.16k
7
        return &(m->second);
1.17k
8
    else
8
9
    {
8
10
      throw std::string("thermometer not found!");
8
11
    }
1.17k
12
}
13
14
THERMOMETER_CONTAINER::THERMOMETER_CONTAINER()
1.05k
15
{
1.05k
16
}
17
18
THERMOMETER::THERMOMETER(int iter):m_stats(iter)
2.11k
19
{
2.11k
20
}
21
22
void THERMOMETER_CONTAINER::add(const std::string &name)
2.11k
23
{
2.11k
24
    auto pair = std::make_pair(name, THERMOMETER(15));
2.11k
25
    thermoMap.insert(pair);
2.11k
26
}
27
28
void THERMOMETER_CONTAINER::setTemp(const std::string &name, double value)
184
29
{
184
30
    returnThermometerPtr(name)->m_thermometer.oldTemp = returnThermometerPtr(name)->m_thermometer.newTemp;
184
31
    returnThermometerPtr(name)->m_thermometer.newTemp = value;
184
32
}
33
34
double THERMOMETER_CONTAINER::getTemp(const std::string &name)
88
35
{
88
36
    return returnThermometerPtr(name)->m_thermometer.newTemp;
88
37
}
38
39
double THERMOMETER_CONTAINER::getOldTemp(const std::string &name)
56
40
{
56
41
    return returnThermometerPtr(name)->m_thermometer.oldTemp;
56
42
}
43
44
TEMPERATURE_STATE THERMOMETER_CONTAINER::getLastState(const std::string &name)
104
45
{
104
46
    return returnThermometerPtr(name)->m_thermometer.lastState;
104
47
}
48
49
void THERMOMETER_CONTAINER::setState(const std::string &name, TEMPERATURE_STATE state)
56
50
{
56
51
    returnThermometerPtr(name)->m_thermometer.lastState = state;
56
52
}
53
54
void THERMOMETER_CONTAINER::updateAll(std::vector<std::string> *vectorThermo)
92
55
{
92
56
    std::string in  = vectorThermo->at(0);
92
57
    std::string out = vectorThermo->at(1);
92
58
    setTemp("inside", std::stod(in));
92
59
    setTemp("outside",std::stod(out));
92
60
}
61
62
void THERMOMETER_CONTAINER::updateStats(const std::string &name)
112
63
{
112
64
    returnThermometerPtr(name)->m_stats.push_back(returnThermometerPtr(name)->m_thermometer.newTemp);
112
65
}
66
67
std::string THERMOMETER_CONTAINER::getStatsByName(const std::string &name)
16
68
{
16
69
    return returnThermometerPtr(name)->m_stats.stats();
16
70
}
71
72
bool THERMOMETER_CONTAINER::isMoreDiff(const std::string &name, double diff)
56
73
{
56
74
    return returnThermometerPtr(name)->m_stats.isMoreDiff(diff);
56
75
}
76
77
std::pair<double, double> THERMOMETER_CONTAINER::getLast2(const std::string &name)
20
78
{
20
79
    return returnThermometerPtr(name)->m_stats.getLast2();
20
80
}
81
82
int THERMOMETER_CONTAINER::sizeOf()
24
83
{
24
84
    return static_cast<int>(thermoMap.size());
24
85
}
86
87
void THERMOMETER_CONTAINER::showAll()
24
88
{
24
89
    for(auto n : thermoMap)
48
90
    {
48
91
        std::cout << n.first << " ";
48
92
    }
24
93
    std::cout << std::endl << "koniec prointowania w " << std::endl;
24
94
}
/home/pi/programowanie/iDom_server_OOP/src/blockQueue/../iDomTools/../iDom_server_OOP.h
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
16
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
8
41
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    RADIO_EQ_CONTAINER *main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/home/pi/programowanie/iDom_server_OOP/src/blockQueue/blockqueue.cpp
1
#include "blockqueue.h"
2
#include "../iDom_server_OOP.h"
3
4
blockQueue::blockQueue()
444
5
{
444
6
}
7
std::mutex blockQueue::mutex_queue_char;
8
std::queue <MPD_COMMAND> blockQueue::_MPD_CommandQ;
9
void blockQueue::_add(MPD_COMMAND X)
224
10
{
224
11
    std::lock_guard <std::mutex> lock (mutex_queue_char);
224
12
    if(_MPD_CommandQ.size() < 10)
220
13
    {
220
14
        _MPD_CommandQ.push(X);
220
15
    }
224
16
    else
4
17
    {
4
18
        log_file_mutex.mutex_lock();
4
19
        log_file_cout << DEBUG << "za dużo danych w kolejce- nie dodaje "<< std::endl;
4
20
        log_file_mutex.mutex_unlock();
4
21
4
22
#ifdef BT_TEST
4
23
        std::string e = "za duzo w kolejce";
4
24
        throw e;
4
25
#endif
4
26
    }
224
27
}
28
29
MPD_COMMAND blockQueue::_get( )
160
30
{
160
31
    MPD_COMMAND temp = MPD_COMMAND::NULL_;
160
32
    std::lock_guard <std::mutex> lock (mutex_queue_char);
160
33
    if (_MPD_CommandQ.empty() == false){
152
34
        temp = _MPD_CommandQ.front();
152
35
        _MPD_CommandQ.pop();
152
36
    }
160
37
    return temp;
160
38
}
39
40
int blockQueue::_size()
13.0M
41
{
13.0M
42
    std::lock_guard <std::mutex> lock (mutex_queue_char);
13.0M
43
    return static_cast<int>(_MPD_CommandQ.size());
13.0M
44
}
45
46
void blockQueue::_clearAll()
232
47
{
232
48
     std::lock_guard <std::mutex> lock (mutex_queue_char);
300
49
     while (_MPD_CommandQ.empty() == false){
68
50
         _MPD_CommandQ.pop();
68
51
     }
232
52
}
/home/pi/programowanie/iDom_server_OOP/src/blockQueue/test/blockqueue_BT.cpp
1
#include <gtest/gtest.h>
2
#include "../blockqueue.h"
3
#include <thread>
4
#include <iostream>
5
6
class blockQueue_Class_fixture : public ::testing::Test
7
{
8
public:
16
9
    blockQueue_Class_fixture()  {  }
10
11
protected:
12
    blockQueue test_q;
13
14
    void SetUp() final
16
15
    {
16
16
        test_q._clearAll();
16
17
        std::cout << "blockQueue_Class_fixture SetUp" << std::endl;
16
18
    }
19
20
    void TearDown() final
16
21
    {
16
22
        std::cout << "blockQueue_Class_fixture TearDown" << std::endl;
16
23
    }
24
    static void getFromQ_thread()
4
25
    {
4
26
        blockQueue q;
86.3k
27
        while(q._size() == 0 )
86.3k
28
        {
86.3k
29
        }
4
30
        EXPECT_EQ(q._get(), MPD_COMMAND::STOP);
12.9M
31
        while(q._size() == 0 )
12.9M
32
        {
12.9M
33
        }
4
34
        EXPECT_EQ(q._get(), MPD_COMMAND::STOP);
4
35
    }
36
37
    static void putToQ_thread(MPD_COMMAND c)
4
38
    {
4
39
        blockQueue q;
4
40
        q._add(c);
4
41
        sleep(1);
4
42
        q._add(c);
4
43
    }
44
};
45
46
TEST_F(blockQueue_Class_fixture, main)
4
47
{
4
48
    test_q._clearAll();
4
49
    EXPECT_EQ(test_q._size(), 0);
4
50
    EXPECT_EQ(test_q._get(), MPD_COMMAND::NULL_);
4
51
    test_q._add(MPD_COMMAND::PLAY);
4
52
    EXPECT_EQ(test_q._size(), 1);
4
53
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
4
54
    EXPECT_EQ(test_q._size(), 0);
4
55
}
56
57
TEST_F(blockQueue_Class_fixture, inThread)
4
58
{
4
59
    std::thread get(blockQueue_Class_fixture::getFromQ_thread);
4
60
    std::thread put(blockQueue_Class_fixture::putToQ_thread,MPD_COMMAND::STOP);
4
61
    get.join();
4
62
    put.join();
4
63
}
64
65
TEST_F(blockQueue_Class_fixture, allClear)
4
66
{
4
67
    EXPECT_EQ(test_q._size(), 0);
4
68
    EXPECT_EQ(test_q._get(), MPD_COMMAND::NULL_);
4
69
    test_q._add(MPD_COMMAND::PLAY);
4
70
    EXPECT_EQ(test_q._size(), 1);
4
71
    test_q._add(MPD_COMMAND::PLAY);
4
72
    EXPECT_EQ(test_q._size(), 2);
4
73
    test_q._clearAll();
4
74
    EXPECT_EQ(test_q._size(), 0);
4
75
}
76
77
TEST_F(blockQueue_Class_fixture, capacityExceeded)
4
78
{
4
79
    EXPECT_EQ(test_q._size(), 0);
4
80
44
81
    for (auto i = 0 ; i <10 ; ++i)
40
82
    {
40
83
      test_q._add(MPD_COMMAND::PLAY);
40
84
    }
4
85
4
86
    EXPECT_THROW(test_q._add(MPD_COMMAND::PLAY), std::string );
4
87
    test_q._clearAll();
4
88
}
/home/pi/programowanie/iDom_server_OOP/src/c_connection/../functions/../blockQueue/../logger/logger.hpp
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
16
84
    {
16
85
        *static_cast<std::ostringstream *>(this) << t;
16
86
        return (*this);
16
87
    }
_ZN6LoggerlsIPcEERS_RKT_
4
84
    {
4
85
        *static_cast<std::ostringstream *>(this) << t;
4
86
        return (*this);
4
87
    }
_ZN6LoggerlsIA16_cEERS_RKT_
12
84
    {
12
85
        *static_cast<std::ostringstream *>(this) << t;
12
86
        return (*this);
12
87
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/home/pi/programowanie/iDom_server_OOP/src/c_connection/../iDom_server_OOP.h
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
16
41
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    RADIO_EQ_CONTAINER *main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/home/pi/programowanie/iDom_server_OOP/src/c_connection/c_connection.cpp
1
#include <iostream>
2
#include "c_connection.h"
3
4
C_connection::C_connection (thread_data *my_data):c_socket(my_data->s_client_sock),
5
    c_from(my_data->from),recv_size(0)
32
6
{
32
7
    this -> pointer = &my_data->pointer;
32
8
    this -> my_data = my_data;
32
9
    this->m_encrypted = my_data->server_settings->encrypted;
32
10
    std::fill(std::begin(c_buffer),std::end(c_buffer),',');
32
11
    onStartConnection();
32
12
}
13
14
C_connection::~C_connection()
32
15
{
32
16
    if( mainCommandHandler != std::nullptr_t())
12
17
    {
12
18
        my_data->mainLCD->set_print_song_state(0);
12
19
        my_data->mainLCD->set_lcd_STATE(2);
12
20
        delete mainCommandHandler;
12
21
    }
32
22
    my_data->mainLCD->set_print_song_state(0);
32
23
    my_data->mainLCD->set_lcd_STATE(2);
32
24
#ifndef BT_TEST
25
    sleep(3);
26
#endif
32
27
    shutdown(c_socket, SHUT_RDWR );
32
28
    useful_F::clearThreadArray(my_data);
32
29
    puts("C_connection::~C_connection()");
32
30
}
31
32
int C_connection::c_send(int para)
4
33
{
4
34
    crypto(str_buf,m_encriptionKey,m_encrypted); //BUG - naprawic czytanie flagi z parametru klasy
4
35
    std::string len = std::to_string( str_buf.size());
4
36
    crypto(len,m_encriptionKey,m_encrypted);
4
37
    if(( send( c_socket, len.c_str() ,len.length(), para ) ) <= 0 )
4
38
    {
4
39
        return -1;
4
40
    }
0
41
    recv_size = recv( c_socket, c_buffer , MAX_buf, para );
0
42
0
43
    if(recv_size < 0 )
0
44
    {
0
45
        log_file_mutex.mutex_lock();
0
46
        log_file_cout << ERROR << "C_connection::c_send(int para) recv() error - " << strerror( errno ) << std::endl;
0
47
        log_file_mutex.mutex_unlock();
0
48
        return -1;
0
49
    }
0
50
    else if (recv_size == 0)
0
51
    {
0
52
        return -1;
0
53
    }
0
54
0
55
    auto len_send = str_buf.length();
0
56
0
57
    while (len_send > 0)
0
58
    {
0
59
        auto len_temp = send( c_socket, str_buf.c_str() ,str_buf.length(), para );
0
60
        if(len_temp <= 0 )
0
61
        {
0
62
            return -1;
0
63
        }
0
64
        len_send -= len_temp;
0
65
        str_buf.erase(0,len_temp);
0
66
    }
0
67
    return 0;
0
68
}
69
70
int C_connection::c_send(const std::string &command )
4
71
{
4
72
    str_buf = command;
4
73
    return c_send(0);
4
74
}
75
76
int C_connection::c_recv(int para)
4
77
{
4
78
    struct timeval tv;
4
79
    tv.tv_sec = 90;
4
80
    tv.tv_usec = 0;
4
81
    setsockopt(c_socket,SOL_SOCKET,SO_RCVTIMEO,(char*)&tv , sizeof(struct timeval));
4
82
4
83
    recv_size = recv(c_socket, c_buffer, MAX_buf, para);
4
84
4
85
    if(recv_size < 0)
4
86
    {
4
87
        log_file_mutex.mutex_lock();
4
88
        log_file_cout << ERROR << "C_connection::c_recv(int para) recv() error - " << strerror( errno ) << std::endl;
4
89
        log_file_mutex.mutex_unlock();
4
90
        return -1;
4
91
    }
0
92
    else if (recv_size == 0)
0
93
    {
0
94
        return -1;
0
95
    }
0
96
    return recv_size;
4
97
}
98
99
void C_connection::c_analyse(int recvSize)
12
100
{
12
101
    std::string buf;
12
102
12
103
    buf = c_read_buf(recvSize);
12
104
    my_data->myEventHandler.run("command")->addEvent(buf);
12
105
    std::vector <std::string> command;
12
106
    try{
12
107
    useful_F::tokenizer(command," \n,", buf);
12
108
    }
4
109
    catch (std::string& k){
4
110
        log_file_mutex.mutex_lock();
4
111
        log_file_cout << DEBUG << "brak komendy - " << k << std::endl;
4
112
        log_file_mutex.mutex_unlock();
4
113
        str_buf = "empty command";
4
114
        return;
4
115
    }
12
116
12
117
#ifdef BT_TEST
8
118
    std::cout << "komenda: " << str_buf << " command.size() " << command.size() << std::endl;
8
119
#endif
8
120
    str_buf = "unknown command\n";
8
121
8
122
    for(std::string t : command)
20
123
    {
20
124
        str_buf += t+" ";
20
125
    }
8
126
8
127
    str_buf = mainCommandHandler->run(command,my_data);
8
128
}
/home/pi/programowanie/iDom_server_OOP/src/c_connection/c_connection2.cpp
1
#include "c_connection.h"
2
#include <iostream>
3
4
std::string C_connection::c_read_buf (int recvSize)
12
5
{
12
6
    std::string str_buf;
136
7
    for (int i = 0; i < recvSize; ++i)
124
8
    {
124
9
        str_buf.push_back( c_buffer[i]);
124
10
    }
12
11
    crypto(str_buf,m_encriptionKey,m_encrypted);
12
12
    return str_buf;
12
13
}
/home/pi/programowanie/iDom_server_OOP/src/c_connection/c_connection_node.cpp
1
2
#include "c_connection.h"
3
#include <iostream>
4
5
//////// not used now
6
//void C_connection::c_start_master ()
7
//{
8
//    std::cout << " w pamieci jest " <<my_data->server_settings->AAS.size() <<" nodow\n";
9
//    for (unsigned int i =0; i<my_data->server_settings->AAS.size(); ++i )
10
//    {
11
//        std::cout << " jest ustawien id " << my_data->server_settings->AAS[i].id << std::endl;
12
//        std::cout << " jest ustawien ip " << my_data->server_settings->AAS[i].SERVER_IP << std::endl;
13
//    }
14
//        while (1)
15
//        {
16
//             //c_recv_master_to();
17
//             c_recv_send_master();
18
//             std::cout << " odebralem w masterze \n";
19
//             //c_send_master_to(c_bufor_tmp[16]);
20
//        }
21
//}
22
23
24
//void C_connection::c_recv_send_master()
25
//{
26
//    while (1)
27
//    {
28
//        std::this_thread::sleep_for( std::chrono::milliseconds(50) );
29
30
//        mutex_who.lock();
31
//        if (pointer->ptr_who[0] == my_data->server_settings->ID_server)
32
//        {
33
//            mutex_buf.lock();
34
35
//            for (int i =0; i < MAX_MSG_LEN; ++i )
36
//            {
37
//                 pointer->ptr_buf[i]-=1;
38
//            }
39
//            pointer->ptr_who[0] = pointer->ptr_who[1];
40
//            pointer->ptr_who[1] = my_data->server_settings->ID_server;
41
//            mutex_buf.unlock();
42
//        }
43
//         mutex_who.unlock();
44
//    } // end while
45
//}
46
47
void C_connection::setEncriptionKey(const std::string& key)
4
48
{
4
49
    m_encriptionKey = key;
4
50
}
51
52
void C_connection::setEncrypted(bool flag)
16
53
{
16
54
    m_encrypted = flag;
16
55
}
56
57
void C_connection::crypto(std::string &toEncrypt, std::string key, bool encrypted)
36
58
{
36
59
    if (!encrypted){
20
60
          return;
20
61
      }
16
62
    unsigned int keySize = key.size()-1;
16
63
#ifdef BT_TEST
16
64
    std::cout << "key: " << key << " size: " << key.size() << std::endl;
16
65
#endif
296
66
    for (unsigned int i = 0; i < toEncrypt.size (); i++)
280
67
    {
280
68
        if (keySize == 0)
24
69
            keySize = key.size()-1;
280
70
        else
256
71
            --keySize;
280
72
        toEncrypt[i] ^= key[keySize];
280
73
    }
16
74
}
75
76
void C_connection::onStartConnection()
32
77
{
32
78
//    log_file_mutex.mutex_lock();
32
79
//    log_file_cout << INFO<< "konstruuje nowy obiekt do komunikacj na gniezdzie " << c_socket << std::endl;
32
80
//    log_file_mutex.mutex_unlock();
32
81
}
82
83
void C_connection::onStopConnection()
4
84
{
4
85
    my_data->main_iDomTools->cameraLedOFF(my_data->server_settings->cameraLedOFF);
4
86
}
87
88
void C_connection::cryptoLog(std::string &toEncrypt)
8
89
{
8
90
    crypto(toEncrypt,m_encriptionKey,m_encrypted);
8
91
}
/home/pi/programowanie/iDom_server_OOP/src/c_connection/test/../c_connection.h
1
#ifndef C_CONNECTION_H
2
#define C_CONNECTION_H
3
#include <mutex>
4
#include <unistd.h>
5
#include <iostream>
6
#include "../functions/functions.h"
7
#include "../CRON/cron.hpp"
8
#include "../functions/mpd_cli.h"
9
#include "../command/commandhandlerroot.h"
10
#include "../iDom_server_OOP.h"
11
12
constexpr int MAX_buf = 32768;
13
14
class C_connection
15
{
16
#ifdef BT_TEST
17
   friend class c_connection_fixture;
18
#endif
19
public:
20
    C_connection(thread_data *my_data);
21
    ~C_connection();
22
23
    thread_data *my_data;
24
    int c_socket;
25
    sockaddr_in c_from;
26
27
    char c_buffer[MAX_buf];
28
    int recv_size;
29
    struct s_pointer *pointer;
30
31
    int c_send(int para);
32
    int c_send(const std::string& command);
33
    int c_recv(int para);
34
    std::string c_read_buf(int recvSize);
35
    void c_analyse(int recvSize);
36
    void setEncriptionKey(const std::string& key);
37
    void setEncrypted(bool flag);
38
    commandHandler *mainCommandHandler = NULL;
39
    void onStartConnection();
40
    void onStopConnection();
41
    void cryptoLog(std::string &toEncrypt);
42
#ifdef BT_TEST
4
43
    std::string getStr_buf(){
4
44
        return str_buf;
4
45
    }
46
#endif
47
private:
48
    std::string str_buf;
49
    blockQueue char_queue;
50
    int counter = 0;
51
    std::string m_encriptionKey;
52
    bool m_encrypted;
53
    void crypto(std::string &toEncrypt, std::string key, bool encrypted);
54
};
55
56
#endif // C_CONNECTION_H
/home/pi/programowanie/iDom_server_OOP/src/c_connection/test/c_connection_BT.cpp
1
#include <gtest/gtest.h>
2
#include "../../iDomTools/test/iDomTools_fixture.h"
3
4
#include "../c_connection.h"
5
6
class c_connection_fixture : public iDomTOOLS_ClassTest
7
{
8
public:
32
9
    c_connection_fixture() {
32
10
        this->test_connection = std::nullptr_t();
32
11
    }
12
13
protected:
14
    C_connection* test_connection;
15
    void SetUp() final
32
16
    {
32
17
        std::cout << "c_connection_fixture SetUp()" << std::endl;
32
18
        iDomTOOLS_ClassTest::SetUp();
32
19
        test_connection = new C_connection(&test_my_data);
32
20
        test_connection->m_encriptionKey = "key";
32
21
        test_connection->m_encrypted = false;
32
22
    }
23
    void TearDown() final
32
24
    {
32
25
        delete test_connection;
32
26
        iDomTOOLS_ClassTest::TearDown();
32
27
        std::cout << "c_connection_fixture TearDown()" << std::endl;
32
28
    }
29
    void crypto_fixture(std::string &toEncrypt, std::string key)
8
30
    {
8
31
        test_connection->crypto(toEncrypt, std::move(key), true);
8
32
    }
33
};
34
35
TEST_F(c_connection_fixture, crypto)
4
36
{
4
37
    std::string key = "210116556";
4
38
    std::string test_msg = "kokosowa ksiezniczka";
4
39
    std::string toEncrypt = test_msg;
4
40
    crypto_fixture(toEncrypt, key);
4
41
84
42
    for(int i = 0; i < toEncrypt.size(); ++i)
80
43
    {
240
44
        EXPECT_NE(test_msg[i],toEncrypt[i]) << " niestety równe: " << toEncrypt[i]
240
45
                                            << " na indeksie: " << i;
80
46
    }
4
47
    std::cout << "wiadomość: " << test_msg << " zakodowane: "<< toEncrypt << std::endl;
4
48
    crypto_fixture(toEncrypt, key);
4
49
    std::cout << "wiadomość: " << test_msg << " odkodowane: "<< toEncrypt << std::endl;
12
50
    EXPECT_STREQ(toEncrypt.c_str(), test_msg.c_str()) << "wiadomosci nie są równe";
4
51
}
52
53
TEST_F(c_connection_fixture, c_analyse)
4
54
{
4
55
    commandHandlerRoot* chr = new commandHandlerRoot(&test_my_data);
4
56
    test_connection->mainCommandHandler = chr;
4
57
    int i = 0;
4
58
    std::string strMsg = "fake command";
4
59
    for (char n : strMsg)
48
60
        test_connection->c_buffer[i++] = n;
4
61
    test_connection->setEncrypted(false);
4
62
    test_connection->c_analyse(strMsg.size());
4
63
    EXPECT_THAT(test_my_data.myEventHandler.run("command")->getEvent()
4
64
                ,testing::HasSubstr(strMsg));
4
65
}
66
67
TEST_F(c_connection_fixture, c_recv)
4
68
{
4
69
    EXPECT_EQ(-1, test_connection->c_recv(1));
4
70
}
71
72
TEST_F(c_connection_fixture, c_send)
4
73
{
4
74
    EXPECT_EQ(-1, test_connection->c_send("test"));
4
75
}
76
77
TEST_F(c_connection_fixture, cryptoLog)
4
78
{
4
79
    std::string msg("tajna wiadomosc");
4
80
    std::string msgBackup(msg);
4
81
    test_connection->setEncriptionKey("key_test");
4
82
    test_connection->setEncrypted(true);
4
83
    ///////szyfrowanie
4
84
    test_connection->cryptoLog(msg);
4
85
    EXPECT_STRNE(msgBackup.c_str(), msg.c_str());
4
86
    std::cout << "ZASZUFROWANY: " << msg << std::endl;
4
87
    ////// deszyfracja
4
88
    test_connection->cryptoLog(msg);
4
89
    EXPECT_STREQ(msgBackup.c_str(), msg.c_str());
4
90
}
91
92
TEST_F(c_connection_fixture, onStopConnection)
4
93
{
4
94
    TEST_DATA::return_httpPost = "ok.\n";
4
95
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"),STATE::UNKNOWN);
4
96
    test_connection->onStopConnection();
4
97
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"),STATE::OFF);
4
98
}
99
100
TEST_F(c_connection_fixture, exitFlow)
4
101
{
4
102
    commandHandlerRoot* chr = new commandHandlerRoot(&test_my_data);
4
103
    test_connection->mainCommandHandler = chr;
4
104
4
105
    int i = 0;
4
106
    std::string strMsg = "program stop server";
4
107
    for (char n : strMsg)
76
108
        test_connection->c_buffer[i++] = n;
4
109
    test_connection->setEncrypted(false);
4
110
    EXPECT_THROW(test_connection->c_analyse(strMsg.size()),std::string );
4
111
}
112
113
TEST_F(c_connection_fixture, emptyCommand)
4
114
{
4
115
    commandHandlerRoot* chr = new commandHandlerRoot(&test_my_data);
4
116
    test_connection->mainCommandHandler = chr;
4
117
4
118
    int i = 0;
4
119
    std::string strMsg = "";
4
120
    for (char n : strMsg)
0
121
        test_connection->c_buffer[i++] = n;
4
122
    test_connection->setEncrypted(false);
4
123
    test_connection->c_analyse(strMsg.size());
4
124
    EXPECT_STREQ(test_connection->getStr_buf().c_str(), "empty command");
4
125
}
/home/pi/programowanie/iDom_server_OOP/src/c_irda_logic/../thread_functions/../iDom_server_OOP.h
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
168
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
80
41
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    RADIO_EQ_CONTAINER *main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/home/pi/programowanie/iDom_server_OOP/src/c_irda_logic/../thread_functions/../logger/logger.hpp
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
12
84
    {
12
85
        *static_cast<std::ostringstream *>(this) << t;
12
86
        return (*this);
12
87
    }
_ZN6LoggerlsIbEERS_RKT_
8
84
    {
8
85
        *static_cast<std::ostringstream *>(this) << t;
8
86
        return (*this);
8
87
    }
_ZN6LoggerlsIA20_cEERS_RKT_
4
84
    {
4
85
        *static_cast<std::ostringstream *>(this) << t;
4
86
        return (*this);
4
87
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/home/pi/programowanie/iDom_server_OOP/src/c_irda_logic/c_irda_logic.cpp
1
#include "c_irda_logic.h"
2
#include "../iDom_server_OOP.h"
3
#include "../thread_functions/iDom_thread.h"
4
5
void c_irda_logic::irdaMPD(PILOT_KEY X)
40
6
{
40
7
    switch (X){
4
8
    case PILOT_KEY::KEY_POWER:
4
9
        mpd_queue._add(MPD_COMMAND::STOP);
4
10
        break;
4
11
    case PILOT_KEY::KEY_TV:
4
12
        mpd_queue._add(MPD_COMMAND::PLAY);
4
13
        break;
4
14
    case PILOT_KEY::KEY_VOLUMEDOWN:
4
15
        mpd_queue._add(MPD_COMMAND::VOLDOWN);
4
16
        break;
4
17
    case PILOT_KEY::KEY_VOLUMEUP:
4
18
        mpd_queue._add(MPD_COMMAND::VOLUP);
4
19
        break;
4
20
    case PILOT_KEY::KEY_AUDIO:
4
21
        mpd_queue._add(MPD_COMMAND::PAUSE);
4
22
        break;
4
23
    case PILOT_KEY::KEY_UP:
4
24
        mpd_queue._add(MPD_COMMAND::NEXT);
4
25
        break;
4
26
    case PILOT_KEY::KEY_DOWN:
4
27
        mpd_queue._add(MPD_COMMAND::PREV);
4
28
        break;
12
29
    default:
12
30
        log_file_mutex.mutex_lock();
12
31
        log_file_cout << CRITICAL << "nieznana komenda MPD z pilota "<< std::endl;
12
32
        log_file_mutex.mutex_unlock();
12
33
        break;
40
34
    }
40
35
}
36
37
void c_irda_logic::sleeperLogic(PILOT_KEY X)
40
38
{
40
39
    my_data->mainLCD->set_print_song_state(100);
40
40
    my_data->mainLCD->printString(true,0,0,std::to_string(my_data->sleeper)+" minut");
40
41
40
42
    switch (X){
4
43
    case PILOT_KEY::KEY_EXIT:
4
44
    {
4
45
        my_data->sleeper=0;
4
46
        my_data->mainLCD->set_print_song_state(0);
4
47
        who = PILOT_STATE::MPD;
4
48
        break;
4
49
    }
16
50
    case PILOT_KEY::KEY_UP:
16
51
    {
16
52
        ++my_data->sleeper;
16
53
        my_data->mainLCD->printString(true,0,0,std::to_string(my_data->sleeper)+" minut");
16
54
        break;
4
55
    }
4
56
    case PILOT_KEY::KEY_DOWN:
4
57
    {
4
58
        --my_data->sleeper;
4
59
        my_data->mainLCD->printString(true,0,0,std::to_string(my_data->sleeper)+" minut");
4
60
        break;
4
61
    }
4
62
    case PILOT_KEY::KEY_CHANNELUP:
4
63
    {
4
64
        my_data->sleeper+=10;
4
65
        my_data->mainLCD->printString(true,0,0,std::to_string(my_data->sleeper)+" minut");
4
66
        break;
4
67
    }
4
68
    case PILOT_KEY::KEY_CHANNELDOWN:
4
69
    {
4
70
        my_data->sleeper-=10;
4
71
        my_data->mainLCD->printString(true,0,0,std::to_string(my_data->sleeper)+" minut");
4
72
        break;
4
73
    }
4
74
    case PILOT_KEY::KEY_OK:
4
75
    {
4
76
        iDOM_THREAD::start_thread("Sleeper MPD",useful_F::sleeper_mpd,my_data);
4
77
        my_data->mainLCD->printString(true,1,0,"SLEEPer START");
4
78
        my_data->mainLCD->set_print_song_state(0);
4
79
        who = PILOT_STATE::MPD;
4
80
        break;
4
81
    }
4
82
    default:
4
83
        log_file_mutex.mutex_lock();
4
84
        log_file_cout << CRITICAL << "nieznany case w sleeperLogic"<< std::endl;
4
85
        log_file_mutex.mutex_unlock();
4
86
        break;
40
87
    }
40
88
}
89
90
void c_irda_logic::projectorLogic(PILOT_KEY X)
48
91
{
48
92
    my_data->mainLCD->set_print_song_state(100);
48
93
    my_data->mainLCD->printString(false,2,1,"  PROJEKTOR   ");
48
94
48
95
    switch (X)
48
96
    {
8
97
    case PILOT_KEY::KEY_EXIT:
8
98
    {
8
99
        my_data->mainLCD->set_print_song_state(0);
8
100
        who = PILOT_STATE::MPD;
8
101
8
102
        if(my_data->ptr_MPD_info->isPlay == true){
4
103
            iDomTOOLS::MPD_play(my_data);
4
104
        }
4
105
        else {
4
106
            iDomTOOLS::turnOffSpeakers();
4
107
            my_data->mainLCD->set_print_song_state(0); // off display
4
108
            my_data->mainLCD->set_lcd_STATE(0);
4
109
        }
8
110
        break;
8
111
    }
4
112
    case PILOT_KEY::DUMMY:
4
113
    {
4
114
        break;
8
115
    }
4
116
    case PILOT_KEY::KEY_VOLUMEUP:
4
117
    {
4
118
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "+");
4
119
        break;
8
120
    }
4
121
    case PILOT_KEY::KEY_VOLUMEDOWN:
4
122
    {
4
123
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "-");
4
124
        break;
8
125
    }
4
126
    case PILOT_KEY::KEY_OK:
4
127
    {
4
128
        my_data->mainLCD->set_print_song_state(1000);
4
129
        my_data->mainLCD->printString(false,0,0,"ODTWARZAM VIDEO");
4
130
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "p");
4
131
        break;
8
132
    }
4
133
    case PILOT_KEY::KEY_POWER:
4
134
    {
4
135
        //system("echo -n q > /mnt/ramdisk/cmd &"); // zamykanie omxplayera
4
136
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "q");
4
137
        break;
8
138
    }
4
139
    case PILOT_KEY::KEY_DOWN:
4
140
    {
4
141
        system("echo -n $'\x1b\x5b\x43' > /mnt/ramdisk/cmd"); // do przodu
4
142
        //write_to_mkfifo("$'\x1b\x5b\x43'");
4
143
        break;
8
144
    }
4
145
    case PILOT_KEY::KEY_UP:
4
146
    {
4
147
        system("echo -n $'\x1b\x5b\x44' > /mnt/ramdisk/cmd"); // do tylu
4
148
        // write_to_mkfifo("$'\x1b\x5b\x44'");
4
149
        break;
8
150
    }
4
151
    case PILOT_KEY::KEY_CHANNELUP:
4
152
    {
4
153
        //system("echo -n o > /mnt/ramdisk/cmd"); // do przodu
4
154
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "o");
4
155
        break;
8
156
    }
4
157
    case PILOT_KEY::KEY_CHANNELDOWN:
4
158
    {
4
159
        //system("echo -n i > /mnt/ramdisk/cmd"); // do tylu
4
160
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "i");
4
161
        break;
8
162
    }
4
163
    default:
4
164
        log_file_mutex.mutex_lock();
4
165
        log_file_cout << CRITICAL << "nieznany case w projector"<< std::endl;
4
166
        log_file_mutex.mutex_unlock();
4
167
        break;
48
168
    }
48
169
}
170
171
void c_irda_logic::movieLogic(PILOT_KEY X)
56
172
{
56
173
    switch (X)
56
174
    {
4
175
    case PILOT_KEY::KEY_EXIT:
4
176
    {
4
177
        my_data->mainLCD->set_print_song_state(0);
4
178
        my_data->mainLCD->set_lcd_STATE(2);
4
179
        who = PILOT_STATE::MPD; // koniec przegladania katalogow
4
180
        break;
4
181
    }
12
182
    case PILOT_KEY::KEY_VOLUMEUP:
12
183
    {
12
184
        my_data->main_tree->next(); // naspteny katalog
12
185
        break;
4
186
    }
20
187
    case PILOT_KEY::KEY_VOLUMEDOWN:
20
188
    {
20
189
        my_data->main_tree->previous(); //poprzedni katalog
20
190
        break;
4
191
    }
12
192
    case PILOT_KEY::KEY_OK:
12
193
    {
12
194
        // whodze w katalog lub odtwarzma plik
12
195
12
196
        if (my_data->main_tree->is_file() == false)
4
197
        {
4
198
            my_data->main_tree->enter_dir();
4
199
            my_data->main_tree->show_list();
4
200
        }
12
201
        else
8
202
        {
8
203
            std::cout << " URUCHAMIAM PLIK! " <<my_data->main_tree->show_list() <<std::endl;
8
204
8
205
            std::string command = "/home/pi/programowanie/iDom_server_OOP/script/PYTHON/iDom_movie.py ";
8
206
            command+=my_data->main_tree->show_list();
8
207
            system(command.c_str());
8
208
            std::cout << " WYSTARTOWALEM!!";
8
209
            my_data->mainLCD->set_lcd_STATE(-1);
8
210
            my_data->mainLCD->printString(true,0,0,"odtwarzam film");
8
211
            my_data->mainLCD->printString(false,0,1,my_data->main_tree->show_list());
8
212
            who = PILOT_STATE::PROJECTOR;
8
213
8
214
            log_file_mutex.mutex_lock();
8
215
            log_file_cout << INFO << "odtwarzam film "<< my_data->ptr_MPD_info->isPlay << std::endl;
8
216
            log_file_mutex.mutex_unlock();
8
217
8
218
            if (my_data->ptr_MPD_info->isPlay == true){
4
219
                iDomTOOLS::MPD_pause(); // projektor wlaczony wiec pauzuje radio
4
220
            }
4
221
            else{
4
222
                iDomTOOLS::turnOnSpeakers();
4
223
                puts("wlaczam glosnik do filmu");
4
224
            }
8
225
        }
12
226
        break;
4
227
    }
4
228
    case PILOT_KEY::KEY_UP:
4
229
    {
4
230
        my_data->main_tree->back_dir();
4
231
        break;
4
232
    }
4
233
    default:
4
234
        log_file_mutex.mutex_lock();
4
235
        log_file_cout << CRITICAL << "nieznany case w moveLogic"<< std::endl;
4
236
        log_file_mutex.mutex_unlock();
4
237
        break;
56
238
    }
56
239
56
240
    my_data->main_tree->show_list();
56
241
}
242
243
void c_irda_logic::menuLogic(PILOT_KEY X)
156
244
{
156
245
    switch (X)
156
246
    {
4
247
    case PILOT_KEY::KEY_EXIT:
4
248
    {
4
249
        my_data->mainLCD->set_print_song_state(0);
4
250
        my_data->mainLCD->set_lcd_STATE(2);
4
251
        who = PILOT_STATE::MPD; // koniec przegladania katalogow
4
252
        break;
4
253
    }
92
254
    case PILOT_KEY::KEY_VOLUMEUP:
92
255
    {
92
256
        my_data->main_MENU->next(); // naspteny katalog
92
257
        break;
4
258
    }
24
259
    case PILOT_KEY::KEY_VOLUMEDOWN:
24
260
    {
24
261
        my_data->main_MENU->previous(); //poprzedni katalog
24
262
        break;
4
263
    }
28
264
    case PILOT_KEY::KEY_OK:
28
265
    {
28
266
        // whodze w katalog lub odtwarzma plik
28
267
28
268
        if (my_data->main_MENU->is_file() == false)
4
269
        {
4
270
            my_data->main_MENU->enter_dir();
4
271
            my_data->main_MENU->show_list();
4
272
        }
28
273
        else
24
274
        {
24
275
            // menu start
24
276
            if (my_data->main_MENU->show_list() == "5.SLEEPer"){
8
277
                std::cout << " POBUDKA!!!!" << std::endl;
8
278
                who=PILOT_STATE::SLEEPER;
8
279
            }
16
280
            else if (my_data->main_MENU->show_list() == "2.TEMPERATURA"){
4
281
                std::cout << " temperatura !!!!" << std::endl;
4
282
                who=PILOT_STATE::MPD;
4
283
                _add(PILOT_KEY::KEY_SAT);
4
284
            }
12
285
            else if (my_data->main_MENU->show_list() == "4.PLIKI"){
12
286
                std::cout << " do filmow" << std::endl;
12
287
                who=PILOT_STATE::MPD;
12
288
                _add(PILOT_KEY::KEY_EPG);
12
289
                _add(PILOT_KEY::KEY_VOLUMEUP);
12
290
            }
24
291
        }
28
292
        break;
4
293
    }
4
294
    case PILOT_KEY::KEY_UP:
4
295
    {
4
296
        my_data->main_MENU->back_dir();
4
297
        break;
4
298
    }
4
299
    default:
4
300
        log_file_mutex.mutex_lock();
4
301
        log_file_cout << CRITICAL << "nieznany case w menuLogic"<< std::endl;
4
302
        log_file_mutex.mutex_unlock();
4
303
        break;
156
304
156
305
    }
156
306
    my_data->main_MENU->show_list();
156
307
}
308
309
void c_irda_logic::mainPilotHandler(PILOT_KEY X)
144
310
{
144
311
    switch (X){
144
312
4
313
    case PILOT_KEY::KEY_RADIO:
4
314
    {
4
315
        who = PILOT_STATE::PROJECTOR;
4
316
        _add(PILOT_KEY::DUMMY);
4
317
        break;
4
318
    }
4
319
4
320
    case PILOT_KEY::KEY_SUBTITLE:
4
321
    {
4
322
        my_data->mainLCD->set_lcd_STATE(10);
4
323
        my_data->mainLCD->printString(true,0,0,"GASZE LEDy");
4
324
        std::string temp_str="";
4
325
        temp_str.erase();
4
326
        temp_str += my_data->main_iDomTools->ledOFF();
4
327
        my_data->mainLCD->printString(false,0,1,temp_str);
4
328
        who=PILOT_STATE::MPD;
4
329
        break;
4
330
    }
4
331
36
332
    case PILOT_KEY::KEY_LANGUAGE:
36
333
    {
36
334
        my_data->mainLCD->set_lcd_STATE(10);
36
335
        my_data->mainLCD->printString(true,0,0,"ZAPALAM LEDy");
36
336
        std::string temp_str = my_data->ptr_pilot_led->colorLED[my_data->ptr_pilot_led->counter].getColorName();
36
337
        my_data->main_iDomTools->ledOn(my_data->ptr_pilot_led->colorLED[my_data->ptr_pilot_led->counter]);
36
338
36
339
        if (++my_data->ptr_pilot_led->counter > my_data->ptr_pilot_led->colorLED.size()-1 )
4
340
        {
4
341
            my_data->ptr_pilot_led->counter=0;
4
342
        }
36
343
36
344
        my_data->mainLCD->printString(false,0,1,temp_str);
36
345
        who = PILOT_STATE::MPD;
36
346
        break;
4
347
    }
4
348
4
349
    case PILOT_KEY::KEY_SAT:
4
350
    {
4
351
        my_data->mainLCD->set_lcd_STATE(10);
4
352
        my_data->mainLCD->printString(true,0,0,"SMOG: "+my_data->main_iDomTools->getSmog()+" mg/m^3");
4
353
        std::string temp_str = "I:";
4
354
        std::vector<std::string> temper = my_data->main_iDomTools->getTemperature();
4
355
        //temp_str += my_data_logic->main_iDomTools->getTemperatureString();// send_to_arduino(my_data_logic,"temperature:2;");
4
356
        temp_str += temper.at(0);
4
357
        temp_str += " O:"+ temper.at(1);
4
358
        my_data->mainLCD->printString(false,0,1,temp_str+" c");
4
359
        who = PILOT_STATE::MPD;
4
360
        break;
4
361
    }
4
362
12
363
    case PILOT_KEY::KEY_EPG:
12
364
        who = PILOT_STATE::MOVIE;
12
365
        my_data->main_tree->show_list(); //printuje pierwszy element
12
366
        my_data->mainLCD->set_print_song_state(100);
12
367
        break;
4
368
28
369
    case PILOT_KEY::KEY_MENU:
28
370
        who = PILOT_STATE::MENU;
28
371
        my_data->main_MENU->show_list();
28
372
        my_data->mainLCD->set_print_song_state(100);
28
373
        break;
4
374
    case PILOT_KEY::KEY_FAVORITES:
4
375
        my_data->main_iDomTools->turnOnOffPrinter();
4
376
        break;
8
377
    case PILOT_KEY::KEY_TEXT:
8
378
        my_data->main_iDomTools->turnOnOff433MHzSwitch("listwa");
8
379
        break;
4
380
    case PILOT_KEY::KEY_REFRESH:
4
381
        my_data->main_iDomTools->startKodi_Thread();
4
382
        break;
40
383
    default:
40
384
        irdaMPD(X);
144
385
    }
144
386
}
387
388
c_irda_logic::c_irda_logic(thread_data *my_data):my_data(my_data)
48
389
{
48
390
    // my_data = my_data;
48
391
    who = PILOT_STATE::MPD;
48
392
}
393
394
void c_irda_logic::_add(PILOT_KEY X)
444
395
{
444
396
    switch (who){
140
397
    case PILOT_STATE::MPD:
140
398
        mainPilotHandler(X);
140
399
        break;
40
400
    case PILOT_STATE::SLEEPER:
40
401
        sleeperLogic(X);
40
402
        break;
48
403
    case PILOT_STATE::PROJECTOR:
48
404
        projectorLogic(X);
48
405
        break;
56
406
    case PILOT_STATE::MOVIE:
56
407
        movieLogic(X);
56
408
        break;
156
409
    case PILOT_STATE::MENU:
156
410
        menuLogic(X);
156
411
        break;
4
412
    default:
4
413
        log_file_mutex.mutex_lock();
4
414
        log_file_cout << CRITICAL << "nieznany pilotState"<< std::endl;
4
415
        log_file_mutex.mutex_unlock();
4
416
        break;
444
417
    }
444
418
}
419
420
//PILOT_KEY c_irda_logic::_get( )
421
//{
422
//    PILOT_KEY temp = PILOT_KEY::DUMMY;
423
//    if (irda_queue.empty() == false){
424
//        temp = irda_queue.front();
425
//        irda_queue.pop();
426
//    }
427
//    return temp;
428
//}
429
430
//int c_irda_logic::_size() const
431
//{
432
//    return irda_queue.size();
433
//}
/home/pi/programowanie/iDom_server_OOP/src/c_irda_logic/test/c_irda_logic_BT.cpp
1
#include <gtest/gtest.h>
2
#include "../../iDom_server_OOP.h"
3
#include "test_data.h"
4
#include "../../../iDom_server_OOP/src/iDomTools/test/iDomTools_fixture.h"
5
#include "../c_irda_logic.h"
6
7
8
class c_irda_logic_fixture : public iDomTOOLS_ClassTest
9
{
10
public:
11
    c_irda_logic* test_irda;
12
    menu_tree* test_menuTree;
13
    files_tree* test_filesTree;
14
    std::string test_omxplayerFile = "../config/cmd_test";
15
    void SetUp()
48
16
    {
48
17
        iDomTOOLS_ClassTest::SetUp();
48
18
        test_irda = new c_irda_logic(&test_my_data);
48
19
        test_menuTree = new menu_tree("../config/MENU/", test_my_data.mainLCD);
48
20
        test_my_data.main_MENU = test_menuTree;
48
21
48
22
        test_filesTree = new files_tree("../config/MOVIE/", test_my_data.mainLCD);
48
23
        test_my_data.main_tree = test_filesTree;
48
24
48
25
        test_my_data.server_settings->omxplayerFile =  test_omxplayerFile;
48
26
48
27
        std::cout << "c_irda_logic_fixture SetUp()"<<std::endl;
48
28
    }
29
30
    void TearDown()
48
31
    {
48
32
        delete test_irda;
48
33
        delete test_menuTree;
48
34
        delete test_filesTree;
48
35
        iDomTOOLS_ClassTest::TearDown();
48
36
        std::cout << "c_irda_logic_fixture TearDown()"<<std::endl;
48
37
    }
38
};
39
40
TEST_F(c_irda_logic_fixture, kodi)
4
41
{
4
42
    std::array<Thread_array_struc,iDomConst::MAX_CONNECTION >test_ThreadArrayStruc;
4
43
44
44
    for (int i = 0 ; i < iDomConst::MAX_CONNECTION; i++)
40
45
        test_ThreadArrayStruc.at(i).thread_socket = i+1;
4
46
    test_ThreadArrayStruc.at(3).thread_socket = 0;
4
47
    test_my_data.main_THREAD_arr = &test_ThreadArrayStruc;
4
48
4
49
    test_my_data.main_iDomTools->unlockHome();
4
50
    test_my_data.main_iDomStatus->setObjectState("music",STATE::PAUSE);
4
51
    test_my_data.main_iDomStatus->setObjectState("speakers",STATE::OFF);
4
52
    test_irda->_add(PILOT_KEY::KEY_REFRESH);
4
53
    sleep(1);
4
54
}
55
56
TEST_F(c_irda_logic_fixture, turnOnOffListwa)
4
57
{
4
58
    test_my_data.main_iDomTools->unlockHome();
4
59
    test_my_data.main_iDomStatus->setObjectState("listwa",STATE::OFF);
4
60
4
61
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("listwa")->getState(), STATE::UNDEFINE);
4
62
    test_irda->_add(PILOT_KEY::KEY_TEXT);
4
63
12
64
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("listwa")->getState(),
12
65
              STATE::ON) << "wrong state: "
12
66
                         << stateToString(test_my_data.main_REC->getEqPointer("listwa")->getState());
4
67
    test_irda->_add(PILOT_KEY::KEY_TEXT);
4
68
12
69
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("listwa")->getState(),
12
70
              STATE::OFF) << "wrong state: "
12
71
                          << stateToString(test_my_data.main_REC->getEqPointer("listwa")->getState());
4
72
}
73
74
TEST_F(c_irda_logic_fixture, turnOnOffPrinter)
4
75
{
4
76
    setReturnPinState(0);
4
77
    test_my_data.main_iDomTools->unlockHome();
4
78
    test_my_data.main_iDomStatus->setObjectState("printer", STATE::OFF);
4
79
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("printer"),
4
80
              STATE::OFF);
4
81
4
82
    test_irda->mainPilotHandler(PILOT_KEY::KEY_FAVORITES);
4
83
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("printer"),
4
84
              STATE::ON);
4
85
    std::cout <<"event: " << test_my_data.myEventHandler.run("230V")->getEvent() <<std::endl;
4
86
}
87
88
TEST_F(c_irda_logic_fixture, irdaMPD)
4
89
{
4
90
    blockQueue test_Q;
4
91
    test_Q._clearAll();
4
92
4
93
    test_irda->_add(PILOT_KEY::KEY_POWER);
4
94
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::STOP);
4
95
4
96
    test_irda->_add(PILOT_KEY::KEY_TV);
4
97
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::PLAY);
4
98
4
99
    test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
4
100
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::VOLDOWN);
4
101
4
102
    test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
4
103
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::VOLUP);
4
104
4
105
    test_irda->_add(PILOT_KEY::KEY_AUDIO);
4
106
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::PAUSE);
4
107
4
108
    test_irda->_add(PILOT_KEY::KEY_UP);
4
109
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::NEXT);
4
110
4
111
    test_irda->_add(PILOT_KEY::KEY_DOWN);
4
112
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::PREV);
4
113
4
114
    test_irda->_add(PILOT_KEY::KEY_2); //default
4
115
    EXPECT_EQ(test_Q._size(), 0);
4
116
}
117
TEST_F(c_irda_logic_fixture, sleeper_Logic_EXIT)
4
118
{
4
119
    test_my_data.sleeper = 0;
4
120
    EXPECT_EQ(test_my_data.sleeper, 0);
4
121
    test_irda->_add(PILOT_KEY::KEY_MENU);
16
122
    do {
16
123
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
16
124
    } while(TEST_DATA::LCD_print != "5.SLEEPer");
20
125
    do {
20
126
        test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
20
127
    } while(TEST_DATA::LCD_print != "5.SLEEPer");
4
128
    test_irda->_add(PILOT_KEY::KEY_OK);
4
129
    test_irda->_add(PILOT_KEY::KEY_UP);
4
130
    EXPECT_EQ(test_my_data.sleeper, 1);
4
131
    test_irda->_add(PILOT_KEY::KEY_UP);
4
132
    EXPECT_EQ(test_my_data.sleeper, 2);
4
133
    test_irda->_add(PILOT_KEY::KEY_EXIT);
4
134
    EXPECT_EQ(test_my_data.sleeper, 0);
4
135
}
136
137
TEST_F(c_irda_logic_fixture, sleeper_Logic_OK)
4
138
{
4
139
    std::cout << test_my_data.main_REC->listAllName() << std::endl;
4
140
4
141
    std::array<Thread_array_struc,iDomConst::MAX_CONNECTION> test_ThreadArrayStruc;
4
142
44
143
    for (int i = 0 ; i < iDomConst::MAX_CONNECTION; i++)
40
144
        test_ThreadArrayStruc.at(i).thread_socket = i+1;
4
145
    test_ThreadArrayStruc.at(3).thread_socket = 0;
4
146
    test_my_data.main_THREAD_arr = &test_ThreadArrayStruc;
4
147
    test_my_data.sleeper = 0;
4
148
    EXPECT_EQ(test_my_data.sleeper, 0);
4
149
    test_irda->_add(PILOT_KEY::KEY_MENU);
16
150
    do {
16
151
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
16
152
    } while(TEST_DATA::LCD_print != "5.SLEEPer");
4
153
    test_irda->_add(PILOT_KEY::KEY_OK);
4
154
    test_irda->_add(PILOT_KEY::KEY_UP);
4
155
    EXPECT_EQ(test_my_data.sleeper, 1);
4
156
    test_irda->_add(PILOT_KEY::KEY_UP);
4
157
    EXPECT_EQ(test_my_data.sleeper, 2);
4
158
    test_irda->_add(PILOT_KEY::KEY_CHANNELUP);
4
159
    EXPECT_EQ(test_my_data.sleeper, 12);
4
160
    test_irda->_add(PILOT_KEY::KEY_CHANNELDOWN);
4
161
    EXPECT_EQ(test_my_data.sleeper, 2);
4
162
    test_irda->_add(PILOT_KEY::KEY_DOWN);
4
163
    EXPECT_EQ(test_my_data.sleeper, 1);
4
164
    test_irda->_add(PILOT_KEY::KEY_OK);
4
165
    sleep(2);
4
166
    EXPECT_EQ(test_my_data.sleeper, 0);
4
167
    test_irda->_add(PILOT_KEY::KEY_EXIT);
4
168
    EXPECT_EQ(test_my_data.sleeper, 0);\
4
169
4
170
    //////////////default
4
171
    test_irda->who = PILOT_STATE::SLEEPER;
4
172
    test_irda->_add(PILOT_KEY::KEY_0); //default
4
173
}
174
175
TEST_F(c_irda_logic_fixture, LED_ON_OFF)
4
176
{
4
177
    EXPECT_EQ( test_my_data.myEventHandler.run("LED")->getLast1minNumberEvent(),0);
40
178
    for (int i = 1 ; i < test_my_data.ptr_pilot_led->colorLED.size()+2; ++i)
36
179
    {
36
180
        test_irda->_add(PILOT_KEY::KEY_LANGUAGE);
36
181
        EXPECT_EQ( test_my_data.myEventHandler.run("LED")->getLast1minNumberEvent(),i);
36
182
        EXPECT_THAT(test_my_data.myEventHandler.run("LED")->getEvent(),
36
183
                    testing::HasSubstr("LED can not start due to home state: UNDEFINE"));
36
184
    }
4
185
    test_irda->_add(PILOT_KEY::KEY_SUBTITLE);
4
186
}
187
TEST_F(c_irda_logic_fixture, temp_smogINFO)
4
188
{
4
189
    TEST_DATA::return_httpPost = "ok.\n";
4
190
    TEST_DATA::return_send_to_arduino = "12:12";
4
191
    test_irda->_add(PILOT_KEY::KEY_MENU);
4
192
    do {
4
193
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
4
194
    } while(TEST_DATA::LCD_print != "2.TEMPERATURA");
4
195
4
196
    test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
4
197
    test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
4
198
    test_irda->_add(PILOT_KEY::KEY_OK);
4
199
    EXPECT_THAT(TEST_DATA::LCD_print, testing::HasSubstr("TEMPERATURA"));
4
200
}
201
202
TEST_F(c_irda_logic_fixture, menu_enter_dir)
4
203
{
4
204
    test_irda->_add(PILOT_KEY::KEY_MENU);
4
205
    test_irda->_add(PILOT_KEY::KEY_OK);
4
206
4
207
    EXPECT_EQ(test_irda->who, PILOT_STATE::MENU);
4
208
    test_irda->_add(PILOT_KEY::KEY_UP);
4
209
    test_irda->_add(PILOT_KEY::KEY_0); //default
4
210
    test_irda->_add(PILOT_KEY::KEY_EXIT);
4
211
    EXPECT_EQ(test_irda->who, PILOT_STATE::MPD);
4
212
}
213
TEST_F(c_irda_logic_fixture, menu_files)
4
214
{
4
215
    blockQueue  test_q;
4
216
    test_q._clearAll();
4
217
    test_my_data.idom_all_state.houseState = STATE::UNLOCK;
4
218
    int timeout = 10;
4
219
    test_irda->_add(PILOT_KEY::KEY_MENU);
12
220
    do {
12
221
        if (--timeout == 0)
0
222
            FAIL()<<"cannot find";
12
223
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
12
224
    } while(TEST_DATA::LCD_print != "4.PLIKI");
4
225
    test_irda->_add(PILOT_KEY::KEY_OK);
4
226
    EXPECT_EQ(test_irda->who, PILOT_STATE::MOVIE);
4
227
    timeout = 10;
8
228
    do {
8
229
        if (--timeout == 0)
0
230
            FAIL()<<"cannot find";
8
231
        test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
8
232
    } while(TEST_DATA::LCD_print != "GAME_OF_THRONES/");
4
233
    test_irda->_add(PILOT_KEY::KEY_OK);
4
234
    test_irda->_add(PILOT_KEY::KEY_UP);
4
235
    EXPECT_STREQ(TEST_DATA::LCD_print.c_str(),"GAME_OF_THRONES/");
4
236
    test_irda->_add(PILOT_KEY::KEY_EXIT);
4
237
    EXPECT_EQ(test_irda->who, PILOT_STATE::MPD);
4
238
    ///////////////// play - no MPD
4
239
4
240
    test_my_data.ptr_MPD_info->isPlay  = false;
4
241
    test_irda->_add(PILOT_KEY::KEY_MENU);
4
242
    timeout = 10;
20
243
    do {
20
244
        if (--timeout == 0)
0
245
            FAIL()<<"cannot find";
20
246
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
20
247
    } while(TEST_DATA::LCD_print != "4.PLIKI");
4
248
    test_irda->_add(PILOT_KEY::KEY_OK);
4
249
    EXPECT_EQ(test_irda->who, PILOT_STATE::MOVIE);
4
250
    timeout = 10;
8
251
    do {
8
252
        if (--timeout == 0)
0
253
            break;
8
254
        test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
8
255
    } while(TEST_DATA::LCD_print != "s01e02");
4
256
    test_irda->_add(PILOT_KEY::KEY_0); //default
4
257
    test_irda->_add(PILOT_KEY::KEY_OK);
4
258
    EXPECT_EQ(test_irda->who, PILOT_STATE::PROJECTOR);
4
259
    test_irda->_add(PILOT_KEY::KEY_EXIT);
4
260
    EXPECT_EQ(test_irda->who, PILOT_STATE::MPD);
4
261
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"),STATE::OFF);
4
262
    ///////////////// play -  MPD
4
263
    test_my_data.ptr_MPD_info->isPlay  = true;
4
264
    EXPECT_TRUE(test_my_data.ptr_MPD_info->isPlay);
4
265
    test_irda->_add(PILOT_KEY::KEY_MENU);
4
266
    timeout = 10;
20
267
    do {
20
268
        if (--timeout == 0)
0
269
            FAIL()<<"cannot find";
20
270
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
20
271
    } while(TEST_DATA::LCD_print != "4.PLIKI");
4
272
    test_irda->_add(PILOT_KEY::KEY_OK);
4
273
    EXPECT_EQ(test_irda->who, PILOT_STATE::MOVIE);
4
274
    timeout = 10;
4
275
    do {
4
276
        if (--timeout == 0)
0
277
            FAIL()<<"cannot find";
4
278
        test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
4
279
    } while(TEST_DATA::LCD_print != "s01e02");
4
280
    test_irda->_add(PILOT_KEY::KEY_OK);
4
281
    EXPECT_EQ(test_irda->who, PILOT_STATE::PROJECTOR);
4
282
4
283
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PAUSE);
4
284
}
285
286
TEST_F(c_irda_logic_fixture, dummy_KEY_RADIO_and_add )
4
287
{
4
288
    test_irda->_add(PILOT_KEY::KEY_RADIO);
4
289
    EXPECT_EQ(test_irda->who, PILOT_STATE::PROJECTOR);
4
290
4
291
    test_irda->who = PILOT_STATE::LED; //not set
4
292
    test_irda->_add(PILOT_KEY::KEY_RADIO);
4
293
}
294
295
TEST_F(c_irda_logic_fixture, projektor)
4
296
{
4
297
    std::string retString;
4
298
    test_irda->who = PILOT_STATE::PROJECTOR;
4
299
    test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
4
300
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
4
301
    std::cout << "DUPA: " << retString.size() << std::endl;
4
302
   // EXPECT_EQ(retString,"+");
4
303
4
304
    test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
4
305
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
4
306
    std::cout << "DUPA: " << retString.size() << std::endl;
4
307
   // EXPECT_EQ(retString,"+");
4
308
4
309
    test_irda->_add(PILOT_KEY::KEY_OK);
4
310
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
4
311
    std::cout << "DUPA: " << retString.size() << std::endl;
4
312
   // EXPECT_EQ(retString,"-");
4
313
4
314
    test_irda->_add(PILOT_KEY::KEY_POWER);
4
315
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
4
316
    std::cout << "DUPA: " << retString.size() << std::endl;
4
317
   // EXPECT_EQ(retString,"q");
4
318
4
319
    test_irda->_add(PILOT_KEY::KEY_DOWN);
4
320
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
4
321
    std::cout << "DUPA: " << retString.size() << std::endl;
4
322
   // EXPECT_EQ(retString,"+");
4
323
4
324
    test_irda->_add(PILOT_KEY::KEY_UP);
4
325
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
4
326
    std::cout << "DUPA: " << retString.size() << std::endl;
4
327
   // EXPECT_EQ(retString,"+");
4
328
4
329
    test_irda->_add(PILOT_KEY::KEY_CHANNELUP);
4
330
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
4
331
    std::cout << "DUPA: " << retString.size() << std::endl;
4
332
   // EXPECT_EQ(retString,"o");
4
333
4
334
    test_irda->_add(PILOT_KEY::KEY_CHANNELDOWN);
4
335
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
4
336
    std::cout << "DUPA: " << retString.size() << std::endl;
4
337
   // EXPECT_EQ(retString,"i");
4
338
4
339
    test_my_data.ptr_MPD_info->isPlay = true;
4
340
    test_irda->_add(PILOT_KEY::KEY_EXIT);
4
341
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
4
342
    std::cout << "DUPA: " << retString.size() << std::endl;
4
343
    EXPECT_EQ(test_irda->who, PILOT_STATE::MPD);
4
344
4
345
    test_my_data.ptr_MPD_info->isPlay = false;
4
346
    test_irda->_add(PILOT_KEY::KEY_EXIT);
4
347
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
4
348
    std::cout << "DUPA: " << retString.size() << std::endl;
4
349
    EXPECT_EQ(test_irda->who, PILOT_STATE::MPD);
4
350
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"),STATE::OFF);
4
351
4
352
    //// dummy
4
353
    test_irda->who = PILOT_STATE::PROJECTOR;
4
354
    test_irda->_add(PILOT_KEY::KEY_0);
4
355
}
/home/pi/programowanie/iDom_server_OOP/src/command/command.cpp
1
#include "command.h"
2
3
command::command(const std::string &commandName ) : commandName(commandName)
644
4
{
644
5
   // std::cout << "konstruktor command"<<std::endl;
644
6
}
7
8
command::~command()
644
9
{
644
10
  // puts("command::~command()");
644
11
}
12
13
std::string command::getCommandName()
448
14
{
448
15
    return commandName;
448
16
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/../../../../iDom_server_OOP/src/iDomStatus/../../libs/useful/useful.h
1
#ifndef Iusefull_H
2
#define Iusefull_H
3
4
#include <iostream>
5
#include <string>
6
#include <vector>
7
#include <ostream>
8
#include <chrono>
9
#include <sstream>
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <iomanip>
13
#ifndef ANDROID
14
#include "json.hpp"
15
#endif
16
17
std::vector<std::string> split_string(const std::string& s, char separator );
18
19
class useful_F_libs {
20
public:
21
    static  void write_to_mkfifo(const std::string& path, const std::string &msg);
22
    static  std::string read_from_mkfifo(const std::string &path);
23
    static size_t  WriteCallback(void *contents, size_t size, size_t nmemb, void *userp);
24
    static std::string find_tag (const std::string &temp);
25
    //////////////////// HTTP req //////////////////////////
26
    static std::string httpPost(const std::string &url, int timeoutSeconds);
27
    static std::string httpPost(const std::string &url);
28
    static void downloadFile(const std::string &url, const std::string &path, int timeoutSeconds);
29
    static std::string replaceAll(std::string str, const std::string& from, const std::string& to);
30
    static std::string removeHtmlTag(std::string &data);
31
    /////////////////////  JSON ////////////////////////////
32
33
#ifndef ANDROID
34
    static nlohmann::json getJson(const std::string &url);
35
#endif
36
};
37
namespace std
38
{
39
40
#ifdef ANDROID
41
template <typename T>
42
int stoi(T s){
43
    return atoi(s.c_str());
44
}
45
#endif
46
47
template <typename T>
48
std::string to_string(T value)
49
{
50
    std::ostringstream os;
51
    os << value;
52
    return os.str();
53
}
54
} // namespace std
55
56
template <typename T>
57
std::string to_string_with_precision(const T a_value, const int n = 4)
58
{
59
    std::ostringstream out;
60
    out << std::setprecision(n) << a_value;
61
    return out.str();
62
}
63
64
struct Clock{
65
private:
66
    std::time_t m_time;
67
#ifdef BT_TEST
68
    static unsigned int m_BT_H;
69
    static unsigned int m_BT_M;
70
#endif
71
public:
72
    unsigned int m_h = 0;
73
    unsigned int m_min = 0;
74
    Clock () {}
75
    Clock(std::string t){
76
        std::vector<std::string> vt = split_string(t,':');
77
        int h = std::stoi(vt.at(0));
78
        int m = std::stoi(vt.at(1));
79
        set(static_cast <unsigned int>(h),static_cast <unsigned int>(m));
80
    }
81
82
    Clock(unsigned int h, unsigned int m) {
83
        set(h,m);
84
    }
85
    /////////////////////////////////////////////////////////////////////////////////////
86
    void set(unsigned int h, unsigned int m){
87
        if (h<24 && m <60){
88
            this->m_h = h;
89
            this->m_min = m;
90
        }
91
        else {
92
            throw 0;
93
        }
94
    }
95
96
    /////////////////////////////////////////////////////////////////////////////////////
97
    const std::string getString(){
98
        std::stringstream ret;
99
        if (m_h < 10) {
100
            ret << "0";
101
        }
102
        ret << m_h;
103
        ret << ":";
104
        if (m_min < 10) {
105
            ret << "0";
106
        }
107
        ret << m_min;
108
        return ret.str();
109
    }
110
    /////////////////////////////////////////////////////////////////////////////////////
111
    bool operator == (const Clock & c){
112
        if ((this->m_h == c.m_h) && (this->m_min == c.m_min)){
113
            return true;
114
        }
115
        else{
116
            return false;
117
        }
118
    }
119
    /////////////////////////////////////////////////////////////////////////////////////
120
    bool operator != (const Clock & c){
121
        if ((this->m_h != c.m_h) || (this->m_min != c.m_min)){
122
            return true;
123
        }
124
        else{
125
            return false;
126
        }
127
    }
128
    /////////////////////////////////////////////////////////////////////////////////////
129
    friend std::ostream & operator<< (std::ostream &w ,  Clock &c) {
130
        return w << c.getString();
131
    }
132
    /////////////////////////////////////////////////////////////////////////////////////
133
    bool operator < (const Clock& c){
134
        if (this->m_h < c.m_h){
135
            return true;
136
        }
137
        else{
138
            if (this->m_h == c.m_h && this->m_min < c.m_min){
139
                return true;
140
            }
141
        }
142
        return false;
143
    }
144
    /////////////////////////////////////////////////////////////////////////////////////
145
    bool operator > (const Clock& c){
146
        if (this->m_h > c.m_h){
147
            return true;
148
        }
149
        else{
150
            if (this->m_h == c.m_h && this->m_min > c.m_min){
151
                return true;
152
            }
153
        }
154
        return false;
155
    }
156
    /////////////////////////////////////////////////////////////////////////////////////
157
    bool operator >= (const Clock& c){
158
        if (this->m_h > c.m_h){
159
            return true;
160
        }
161
        else if (this->m_h == c.m_h){
162
163
            if (this->m_min >= c.m_min){
164
                return true;
165
            }
166
        }
167
        return false;
168
    }
169
    /////////////////////////////////////////////////////////////////////////////////////
170
    bool operator <= (const Clock& c){
171
        if (this->m_h < c.m_h){
172
            return true;
173
        }
174
        else if (this->m_h == c.m_h){
175
176
            if (this->m_min <= c.m_min){
177
                return true;
178
            }
179
        }
180
        return false;
181
    }
182
    /////////////////////////////////////////////////////////////////////////////////////
183
    Clock  operator + (const Clock& c){
184
        unsigned int minutes, hours;
185
        minutes = m_min+ c.m_min;
186
        hours = m_h + c.m_h;
187
        if (minutes >59){
188
            minutes =  minutes % 60;
189
            hours+=1;
190
        }
191
        if (hours >= 24){
192
            hours-=24;
193
        }
194
        return  Clock(hours, minutes);
195
196
    }
197
    /////////////////////////////////////////////////////////////////////////////////////
198
    Clock&  operator += (const Clock& c){
199
        unsigned int minutes, hours;
200
        minutes = m_min+ c.m_min;
201
        hours = m_h + c.m_h;
202
        if (minutes >59){
203
            minutes =  minutes % 60;
204
            hours+=1;
205
        }
206
        if (hours >= 24){
207
            hours-=24;
208
        }
209
        this->m_h = hours;
210
        this->m_min = minutes;
211
        return *this;
212
213
    }
214
    /////////////////////////////////////////////////////////////////////////////////////
215
216
    unsigned int toSeconds(){
217
        return toSeconds(Clock(this->m_h, this->m_min) );
218
    }
219
    /////////////////////////////////////////////////////////////////////////////////////
220
221
    static unsigned int toSeconds(Clock t){
222
        return ((t.m_h*60) + t.m_min)*60;
223
    }
224
    /////////////////////////////////////////////////////////////////////////////////////
225
226
    static Clock fromSeconds(unsigned int sec){
227
        unsigned int h = sec/3600;
228
        unsigned int min = sec%3600;
229
        min = min/60;
230
        return Clock(h,min);
231
    }
232
    /////////////////////////////////////////////////////////////////////////////////////
233
234
    static Clock periodOfTime(Clock start, Clock end)
235
    {
236
        if (end >= start){
237
            return Clock::fromSeconds(end.toSeconds() - start.toSeconds()  );
238
        }
239
        else{
240
            return Clock::fromSeconds(end.toSeconds() + ( Clock::toSeconds(Clock(23,59))+ 60 - start.toSeconds() ) );
241
        }
242
        //return diff;
243
    }
244
    ////////////////////////////////////////////////////////////////////////////////////
245
    static unsigned int getUnixTime()
16
246
    {
16
247
        return static_cast<unsigned int> (std::time(nullptr));
16
248
    }
249
    /////////////////////////////////////////////////////////////////////////////////////
250
#ifdef BT_TEST
251
    static void setTime_forBT_usage(int h, int m)
252
    {
253
        m_BT_H = h;
254
        m_BT_M = m;
255
    }
256
#endif
257
    /////////////////////////////////////////////////////////////////////////////////////
258
    static Clock getTime()
259
    {
260
#ifdef BT_TEST
261
        return Clock(m_BT_H,m_BT_M);
262
#else
263
        time_t now = time(0);
264
        tm *ltm = localtime(&now);
265
        return Clock( static_cast <unsigned int>(ltm->tm_hour),static_cast <unsigned int>(ltm->tm_min) );
266
#endif
267
    }
268
    /////////////////////////////////////////////////////////////////////////////////////
269
    void stopwatchStart()
270
    {
271
        m_time = std::time(nullptr);
272
    }
273
    /////////////////////////////////////////////////////////////////////////////////////
274
    unsigned int  stopwatchStopAndGetResult()
275
    {
276
        return static_cast<unsigned int>(std::time(nullptr) - m_time);
277
    }
278
};
279
280
enum class STATE {
281
    OFF,
282
    ON,
283
    UNKNOWN,
284
    PLAY,
285
    PAUSE,
286
    STOP,
287
    ACTIVE,
288
    DEACTIVE,
289
    WORKING,
290
    DEFINE,
291
    UNDEFINE,
292
    LOCK,
293
    UNLOCK,
294
    EMPTY,
295
    FULL,
296
    SEND_OK,
297
    SEND_NOK
298
    //WARNING remember add new state to stateToString() usefull.cpp
299
};
300
301
302
std::string stateToString(STATE s);
303
STATE stringToState(const std::string& s);
304
305
#endif
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/../../../../iDom_server_OOP/src/iDomTools/../iDom_server_OOP.h
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
0
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
0
41
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    RADIO_EQ_CONTAINER *main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/../../../../iDom_server_OOP/src/logger/logger.hpp
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
0
84
    {
0
85
        *static_cast<std::ostringstream *>(this) << t;
0
86
        return (*this);
0
87
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/../../../ftplibpp/ftplib.h
1
/***************************************************************************
2
                          ftplib.h  -  description
3
                             -------------------
4
    begin                : Son Jul 27 2003
5
    copyright            : (C) 2013 by magnus kulke
6
    email                : mkulke@gmail.com
7
 ***************************************************************************/
8
9
/***************************************************************************
10
 *                                                                         *
11
 *   This program is free software; you can redistribute it and/or modify  *
12
 *   it under the terms of the GNU Lesser General Public License as        * 
13
 *   published by the Free Software Foundation; either version 2.1 of the  *
14
 *   License, or (at your option) any later version.                       *
15
 *                                                                         *
16
 ***************************************************************************/
17
 
18
/***************************************************************************
19
 * Note: ftplib, on which ftplibpp was originally based upon used to be    *
20
 * licensed as GPL 2.0 software, as of Jan. 26th 2013 its author Thomas    *
21
 * Pfau allowed the distribution of ftplib via LGPL. Thus the license of   *
22
 * ftplibpp changed aswell.                                                *
23
 ***************************************************************************/
24
 
25
#ifndef FTPLIB_H
26
#define FTPLIB_H
27
28
#if defined(_WIN32)
29
30
#if BUILDING_DLL
31
# define DLLIMPORT __declspec (dllexport)
32
#else /* Not BUILDING_DLL */
33
# define DLLIMPORT __declspec (dllimport)
34
#endif /* Not BUILDING_DLL */
35
36
#include <time.h>
37
#endif
38
39
#ifndef _WIN32
40
#include <unistd.h>
41
#include <sys/time.h>
42
#endif
43
44
#ifdef NOLFS
45
#define off64_t long
46
#endif
47
48
#if defined(__APPLE__)
49
#define off64_t __darwin_off_t
50
#define fseeko64 fseeko
51
#define fopen64 fopen
52
#endif
53
54
#ifndef NOSSL
55
#include <openssl/ssl.h>
56
#endif
57
58
#ifndef _FTPLIB_SSL_CLIENT_METHOD_
59
#define _FTPLIB_SSL_CLIENT_METHOD_ TLSv1_2_client_method
60
#endif//_FTPLIB_SSL_CLIENT_METHOD_
61
62
using namespace std;
63
64
/**
65
  *@author mkulke
66
  */
67
68
typedef int (*FtpCallbackXfer)(off64_t xfered, void *arg);
69
typedef int (*FtpCallbackIdle)(void *arg);
70
typedef void (*FtpCallbackLog)(char *str, void* arg, bool out);
71
72
#ifndef NOSSL
73
typedef bool (*FtpCallbackCert)(void *arg, X509 *cert);
74
#endif
75
76
struct ftphandle {
77
	char *cput,*cget;
78
	int handle;
79
	int cavail,cleft;
80
	char *buf;
81
	int dir;
82
	ftphandle *ctrl;
83
	int cmode;
84
	struct timeval idletime;
85
	FtpCallbackXfer xfercb;
86
	FtpCallbackIdle idlecb;
87
	FtpCallbackLog logcb;
88
	void *cbarg;
89
	off64_t xfered;
90
	off64_t cbbytes;
91
	off64_t xfered1;
92
	char response[256];
93
#ifndef NOSSL
94
	SSL* ssl;
95
	SSL_CTX* ctx;
96
	BIO* sbio;
97
	int tlsctrl;
98
	int tlsdata;
99
	FtpCallbackCert certcb;
100
#endif
101
	off64_t offset;
102
	bool correctpasv;
103
};
104
105
#if defined(_WIN32)  
106
class DLLIMPORT ftplib {
107
#else
108
class ftplib {
109
#endif
110
public:
111
112
	enum accesstype
113
	{
114
		dir = 1,
115
		dirverbose,
116
		fileread,
117
		filewrite,
118
		filereadappend,
119
		filewriteappend
120
	}; 
121
122
	enum transfermode
123
	{
124
		ascii = 'A',
125
		image = 'I'
126
	};
127
128
	enum connmode
129
	{
130
		pasv = 1,
131
		port
132
	};
133
134
	enum fxpmethod
135
	{
136
		defaultfxp = 0,
137
        alternativefxp
138
	};
139
140
    enum dataencryption
141
    {
142
        unencrypted = 0,
143
        secure
144
    };
145
146
	ftplib();
147
	~ftplib();
148
    char* LastResponse();
149
    int Connect(const char *host);
150
    int Login(const char *user, const char *pass);
151
    int Site(const char *cmd);
152
    int Raw(const char *cmd);
153
    int SysType(char *buf, int max);
154
    int Mkdir(const char *path);
155
    int Chdir(const char *path);
156
    int Cdup();
157
    int Rmdir(const char *path);
158
    int Pwd(char *path, int max);
159
    int Nlst(const char *outputfile, const char *path);
160
    int Dir(const char *outputfile, const char *path);
161
    int Size(const char *path, int *size, transfermode mode);
162
    int ModDate(const char *path, char *dt, int max);
163
    int Get(const char *outputfile, const char *path, transfermode mode, off64_t offset = 0);
164
    int Put(const char *inputfile, const char *path, transfermode mode, off64_t offset = 0);
165
    int Rename(const char *src, const char *dst);
166
    int Delete(const char *path);
167
#ifndef NOSSL    
168
	int SetDataEncryption(dataencryption enc);
169
    int NegotiateEncryption();
170
	void SetCallbackCertFunction(FtpCallbackCert pointer);
171
#endif
172
    int Quit();
173
    void SetCallbackIdleFunction(FtpCallbackIdle pointer);
174
    void SetCallbackLogFunction(FtpCallbackLog pointer);
175
	void SetCallbackXferFunction(FtpCallbackXfer pointer);
176
	void SetCallbackArg(void *arg);
177
    void SetCallbackBytes(off64_t bytes);
0
178
	void SetCorrectPasv(bool b) { mp_ftphandle->correctpasv = b; };
179
    void SetCallbackIdletime(int time);
180
    void SetConnmode(connmode mode);
181
    static int Fxp(ftplib* src, ftplib* dst, const char *pathSrc, const char *pathDst, transfermode mode, fxpmethod method);
182
    
183
	ftphandle* RawOpen(const char *path, accesstype type, transfermode mode);
184
	int RawClose(ftphandle* handle); 
185
	int RawWrite(void* buf, int len, ftphandle* handle);
186
	int RawRead(void* buf, int max, ftphandle* handle); 
187
188
private:
189
    ftphandle* mp_ftphandle;
190
191
    int FtpXfer(const char *localfile, const char *path, ftphandle *nControl, accesstype type, transfermode mode);
192
    int FtpOpenPasv(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd);
193
    int FtpSendCmd(const char *cmd, char expresp, ftphandle *nControl);
194
    int FtpAcceptConnection(ftphandle *nData, ftphandle *nControl);
195
    int FtpOpenPort(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd);
196
    int FtpRead(void *buf, int max, ftphandle *nData);
197
    int FtpWrite(void *buf, int len, ftphandle *nData);
198
    int FtpAccess(const char *path, accesstype type, transfermode mode, ftphandle *nControl, ftphandle **nData);
199
    int FtpClose(ftphandle *nData);
200
	
201
	int socket_wait(ftphandle *ctl);
202
    int readline(char *buf,int max,ftphandle *ctl);
203
    int writeline(char *buf, int len, ftphandle *nData);
204
    int readresp(char c, ftphandle *nControl);
205
	
206
	void ClearHandle();
207
	int CorrectPasvResponse(unsigned char *v);
208
};
209
210
#endif
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/../../433MHz/RFLink/rflinkhandler.h
1
#ifndef RFLINKHANDLER_H
2
#define RFLINKHANDLER_H
3
4
#include <map>
5
#include <exception>
6
#include "../../SerialPi/serialpi.h"
7
#include "../../iDom_server_OOP.h"
8
9
class WRONG_FORMAT : public std::exception{
10
11
};
12
13
struct RFLink_DEV{
14
    int m_counter = 0;
15
    std::string msg;
36
16
    void counter(){
36
17
        ++m_counter;
36
18
    }
19
8
20
    std::string read(){
8
21
        return std::to_string(m_counter) + " \t"+ msg;
8
22
    }
23
};
24
25
class RFLinkHandler
26
{
27
    thread_data *my_data;
28
    SerialPi serial_RFLink;
29
30
public:
31
32
    static std::mutex sm_RFLink_MUTEX;
33
    static std::string sm_RFLink_BUFOR;
34
35
    unsigned int okTime = 0;
36
    unsigned int pingTime = 0;
37
    ////// temporarnie //////
38
    std::map<std::string, RFLink_DEV> rflinkMAP;
39
    /////////////////////////////
40
    RFLinkHandler(thread_data *my_data);
41
42
    bool init();
43
    // void run();
44
    void flush();
45
    void sendCommand(std::string cmd);
46
    std::string sendCommandAndWaitForReceive(std::string cmd);
47
    std::string readFromRS232();
48
private:
49
    std::string internalReadFromRS232();
50
//#ifdef BT_TEST
51
public:
52
//#endif
53
    static std::string getArgumentValueFromRFLinkMSG(const std::string &msg, const std::string &var);
54
};
55
56
#endif // RFLINKHANDLER_H
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/../../RADIO_433_eq/radio_433_eq.h
1
#ifndef RADIO_SWITCH_H
2
#define RADIO_SWITCH_H
3
#include <gtest/gtest.h>
4
#include <gmock/gmock.h>
5
#include <map>
6
#include "../iDomStatus/idomstatus.h"
7
#include "../433MHz/RFLink/rflinkhandler.h"
8
9
#include "../433MHz/rc_433mhz.h"
10
#include "json.hpp"
11
12
struct WEATHER_STRUCT{
13
private:
14
    unsigned long int m_counter = 0;
15
protected:
16
    unsigned int m_humidity = 0;
17
    double m_temperature = 0.0;
18
    unsigned int m_barometricPressure = 0;
19
public:
20
    unsigned int getHumidity(){ return m_humidity; }
21
    double getTemperature(){ return m_temperature; }
22
    unsigned int getBarometricPressure(){ return m_barometricPressure; }
23
    std::string getDataString(){
24
        return "data: "+std::to_string(m_counter)+"\n"+"Humidity=" + std::to_string(getHumidity()) +"%\n"+
25
                "temperature= " + to_string_with_precision(getTemperature()) + "c\n"+
26
                "Pressure= " + std::to_string(getBarometricPressure())+ "kPa\n";
27
    }
28
29
    void putData(std::string data){
30
        std::string tempStr;
31
        int t = 0;
32
        ++m_counter;
33
        try{
34
            m_humidity = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "HUM") );
35
        }
36
        catch (...){ }
37
        try{
38
            m_barometricPressure = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "BARO") );
39
        }
40
        catch (...){ }
41
        try{
42
            tempStr = RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "TEMP");
43
            std::stringstream ss;
44
            ss << std::hex << tempStr.substr(tempStr.size()-3,tempStr.size());
45
            ss >> t;
46
            m_temperature = t / 10.0;
47
            if(tempStr.at(0) == '8'){
48
                m_temperature *= -1.0;
49
            }
50
        }
51
        catch (...){ }
52
        //std::cout << "DUPA: "<<data<<" temp=" << m_temperature<< " hum="<<m_humidity<< std::endl;
53
    }
54
};
55
56
enum class RADIO_EQ_TYPE{
57
    SWITCH = 1,
58
    PIR,
59
    GATE,
60
    BUTTON,
61
    WEATHER_S,
62
    NONE
63
};
64
struct RADIO_EQ_CONFIG{
65
    std::string name = "NULL";
66
    std::string ID   = "NULL";
67
    std::string type = "NULL";
68
    std::string onCode  = "NULL";
69
    std::string offCode = "NULL";
70
    std::string on15sec = "NULL";
71
    std::string sunrise = "NULL";
72
    std::string sunset  = "NULL";
73
    std::string lock   = "NULL";
74
    std::string unlock = "NULL";
75
    void set(std::string type,
76
             std::string name,
77
             std::string ID,
78
             std::string onCode = "null",
79
             std::string offCode = "null",
80
             std::string on15sec = "null",
81
             std::string sunrise = "null",
82
             std::string sunset = "null",
83
             std::string lock = "null",
24
84
             std::string unlock = "null"){
24
85
        this->name = name;
24
86
        this->ID   = ID;
24
87
        this->type = type;
24
88
        this->onCode  = onCode;
24
89
        this->offCode = offCode;
24
90
        this->on15sec = on15sec;
24
91
        this->sunrise = sunrise;
24
92
        this->sunset  = sunset;
24
93
        this->lock   = lock;
24
94
        this->unlock = unlock;
24
95
    }
96
97
    nlohmann::json getJson(){
98
        nlohmann::json jj;
99
        jj["name"]  = name;
100
        jj["id"]    = ID;
101
        jj["type"]  = type;
102
        jj["ON"]    = onCode;
103
        jj["OFF"]   = offCode;
104
        jj["on15sec"] = on15sec;
105
        jj["sunrise"] = sunrise;
106
        jj["sunset"]  = sunset;
107
        jj["lock"]   = lock;
108
        jj["unlock"] = unlock;
109
        return jj;
110
    }
111
};
112
113
class RADIO_EQ{
114
public:
115
    RADIO_EQ();
116
    virtual ~RADIO_EQ();
117
    virtual STATE getState() = 0;
118
    virtual std::string getName() = 0;
119
    virtual std::string getID() = 0;
120
    virtual RADIO_EQ_TYPE getType();
121
protected:
122
    thread_data *m_my_data;
123
    RADIO_EQ_TYPE m_type;
124
public:
125
    RADIO_EQ_CONFIG m_config;
126
};
127
class RADIO_WEATHER_STATION: public RADIO_EQ
128
{
129
    STATE m_state = STATE::UNDEFINE;
130
131
public:
132
    RADIO_WEATHER_STATION(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
133
    ~RADIO_WEATHER_STATION();
134
    STATE getState();
135
    std::string getName();
136
    std::string getID();
137
    // data
138
    WEATHER_STRUCT data;
139
};
140
class RADIO_BUTTON: public RADIO_EQ
141
{
142
    STATE m_state = STATE::UNDEFINE;
143
144
public:
145
    RADIO_BUTTON(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
146
    ~RADIO_BUTTON();
147
    STATE getState();
148
    void setState(STATE s);
149
    std::string getName();
150
    std::string getID();
151
};
152
153
class RADIO_SWITCH: public RADIO_EQ
154
{
155
#ifdef BT_TEST
156
public:
157
#endif
158
    RC_433MHz main433MHz;
159
    STATE m_state = STATE::UNDEFINE;
160
public:
161
    RADIO_SWITCH(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
162
    ~RADIO_SWITCH();
163
    void on();
164
    void off();
165
    void onFor15sec();
166
    void onSunrise();
167
    void onSunset();
168
    void onLockHome();
169
    void onUnlockHome();
170
    STATE getState();
171
    std::string getName();
172
    std::string getID();
173
    void setCode(RADIO_EQ_CONFIG cfg);
174
    STATE m_sunrise = STATE::UNDEFINE;
175
    STATE m_sunset  = STATE::UNDEFINE;
176
};
177
178
class RADIO_EQ_CONTAINER
179
{
180
    std::map <std::string, RADIO_EQ* > m_radioEqMap;
181
    thread_data * my_data;
182
    nlohmann::json m_configJson;
183
public:
184
    RADIO_EQ_CONTAINER(thread_data * my_data);
185
    virtual ~RADIO_EQ_CONTAINER();
186
    void addRadioEq(RADIO_EQ_CONFIG cfg, RADIO_EQ_TYPE type);
187
    void addRadioEq(RADIO_EQ_CONFIG cfg, const std::string& type);
188
    void deleteRadioEq(const std::string &name);
189
    virtual RADIO_EQ* getEqPointer(std::string name);
190
    std::vector<RADIO_SWITCH*> getSwitchPointerVector();
191
    std::vector<RADIO_BUTTON*> getButtonPointerVector();
192
    std::vector<RADIO_WEATHER_STATION *> getWeather_StationPtrVector();
193
    std::string listAllName();
194
    bool nameExist(const std::string &name);
195
    void loadConfig(const std::string &filePath);
196
    void saveConfig(const std::string &filePath);
197
};
198
199
class RADIO_EQ_CONTAINER_STUB : public RADIO_EQ_CONTAINER
200
{
201
    thread_data * k;
202
public:
203
    RADIO_EQ_CONTAINER_STUB(thread_data * k):RADIO_EQ_CONTAINER(k){this->k = k;}
204
205
    virtual ~RADIO_EQ_CONTAINER_STUB(){puts("~RADIO_EQ_CONTAINER_STUB()");}
206
    MOCK_METHOD1(getEqPointer, RADIO_EQ*(std::string name));
207
};
208
209
#endif // RADIO_SWITCH_H
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/TEST/command_433mhz_BT.cpp
1
#include "../command_433mhz.h"
2
#include "../../../functions/functions.h"
3
#include "../../../RADIO_433_eq/radio_433_eq.h"
4
#include "../../../433MHz/RFLink/rflinkhandler.h"
5
#include "../../../iDomTools/test/iDomTools_fixture.h"
6
7
class command433MHz_Class_fixture : public iDomTOOLS_ClassTest
8
{
9
public:
10
    command433MHz_Class_fixture()
52
11
    {
52
12
        this->test_command_433MHz = std::nullptr_t();
52
13
        this->test_RFLink = std::nullptr_t();
52
14
    }
15
16
protected:
17
    std::vector<std::string> test_v= {"433MHz"};
18
    RFLinkHandler* test_RFLink;
19
    blockQueue test_q;
20
    command_433MHz* test_command_433MHz;
21
22
    void SetUp() final
52
23
    {
52
24
        iDomTOOLS_ClassTest::SetUp();
52
25
52
26
        test_q._clearAll();
52
27
52
28
        test_RFLink = new RFLinkHandler(&test_my_data);
52
29
        test_command_433MHz = new command_433MHz("433MHz");
52
30
        test_my_data.main_RFLink = test_RFLink;
52
31
        std::cout << "command433MHz_Class_fixture SetUp" << std::endl;
52
32
    }
33
34
    void TearDown() final
52
35
    {
52
36
        iDomTOOLS_ClassTest::TearDown();
52
37
        delete test_RFLink;
52
38
        delete test_command_433MHz;
52
39
        std::cout << "command433MHz_Class_fixture TearDown" << std::endl;
52
40
    }
41
42
    void addSwitch(const std::string& name)
4
43
    {
4
44
        test_v.clear();
4
45
        test_v.push_back("433MHz");
4
46
        test_v.push_back("add");
4
47
        test_v.push_back("SWITCH");
4
48
        test_v.push_back(name);
4
49
        test_v.push_back("1234");
4
50
        test_v.push_back("onCode_A");
4
51
        test_v.push_back("ofCode_A");
4
52
        test_v.push_back("on15sec_A");
4
53
        test_v.push_back("sunrise_A");
4
54
        test_v.push_back("sunset_A");
4
55
        test_v.push_back("lock_A");
4
56
        test_v.push_back("unlock_A");
4
57
        std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
58
    }
59
    void deleteSwitch(const std::string& name)
8
60
    {
8
61
        test_v.clear();
8
62
        test_v.push_back("433MHz");
8
63
        test_v.push_back("delete");
8
64
        test_v.push_back(name);
8
65
        std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
8
66
    }
67
};
68
TEST_F(command433MHz_Class_fixture, getCommandName)
4
69
{
4
70
    EXPECT_THAT(test_command_433MHz->getCommandName(),testing::HasSubstr("433MHz"));
4
71
}
72
73
TEST_F(command433MHz_Class_fixture, deleteSwitch)
4
74
{
4
75
    test_v.push_back("show");
4
76
    test_v.push_back("all");
4
77
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
78
    auto v = test_rec.getSwitchPointerVector();
4
79
    EXPECT_EQ(v.size(),5);
4
80
    test_v.clear();
4
81
    test_v.push_back("433MHz");
4
82
    test_v.push_back("delete");
4
83
    test_v.push_back("A");
4
84
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
85
    v = test_rec.getSwitchPointerVector();
4
86
    EXPECT_EQ(v.size(),4);
4
87
    test_v.clear();
4
88
    test_v.push_back("433MHz");
4
89
    test_v.push_back("show");
4
90
    test_v.push_back("all");
4
91
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
92
    addSwitch("A");
4
93
4
94
}
95
TEST_F(command433MHz_Class_fixture, deleteFakeSwitch)
4
96
{
4
97
    int actualSize = test_rec.getSwitchPointerVector().size();
4
98
    test_v.push_back("show");
4
99
    test_v.push_back("all");
4
100
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
101
    auto v = test_rec.getSwitchPointerVector();
4
102
    EXPECT_EQ(v.size(),actualSize);
4
103
    test_v.clear();
4
104
    test_v.push_back("433MHz");
4
105
    test_v.push_back("delete");
4
106
    test_v.push_back("fake");
4
107
    std::string  result = test_command_433MHz->execute(test_v,&test_my_data);
4
108
    EXPECT_THAT(result, testing::HasSubstr("not exist"));
4
109
    v = test_rec.getSwitchPointerVector();
4
110
    EXPECT_EQ(v.size(),actualSize);
4
111
    test_v.clear();
4
112
    test_v.push_back("433MHz");
4
113
    test_v.push_back("show");
4
114
    test_v.push_back("all");
4
115
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
116
}
117
TEST_F(command433MHz_Class_fixture, addButton)
4
118
{
4
119
    int actualSize = test_rec.getButtonPointerVector().size();
4
120
    test_v.push_back("show");
4
121
    test_v.push_back("all");
4
122
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
123
    auto v = test_rec.getButtonPointerVector();
4
124
    EXPECT_EQ(v.size(),actualSize);
4
125
    test_v.clear();
4
126
    test_v.push_back("433MHz");
4
127
    test_v.push_back("add");
4
128
    test_v.push_back("BUTTON");
4
129
    test_v.push_back("glowny");
4
130
    test_v.push_back("4321");
4
131
    test_v.push_back("onCode");
4
132
    test_v.push_back("offCode");
4
133
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
134
    v = test_rec.getButtonPointerVector();
4
135
    EXPECT_EQ(v.size(),actualSize+1);
4
136
    test_v.clear();
4
137
    test_v.push_back("433MHz");
4
138
    test_v.push_back("show");
4
139
    test_v.push_back("all");
4
140
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
141
    deleteSwitch("glowny");
4
142
}
143
144
TEST_F(command433MHz_Class_fixture, addSwitch)
4
145
{
4
146
    int actualSize = test_rec.getSwitchPointerVector().size();
4
147
    test_v.push_back("show");
4
148
    test_v.push_back("all");
4
149
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
150
    auto v = test_rec.getSwitchPointerVector();
4
151
    EXPECT_EQ(v.size(),actualSize);
4
152
    test_v.clear();
4
153
    test_v.push_back("433MHz");
4
154
    test_v.push_back("add");
4
155
    test_v.push_back("SWITCH");
4
156
    test_v.push_back("Aaa");
4
157
    test_v.push_back("1234");
4
158
    test_v.push_back("onCode_A");
4
159
    test_v.push_back("ofCode_A");
4
160
    test_v.push_back("on15sec_A");
4
161
    test_v.push_back("sunrise_A");
4
162
    test_v.push_back("sunset_A");
4
163
    test_v.push_back("lock_A");
4
164
    test_v.push_back("unlock_A");
4
165
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
166
    v = test_rec.getSwitchPointerVector();
4
167
    EXPECT_EQ(v.size(),actualSize+1);
4
168
    test_v.clear();
4
169
    test_v.push_back("433MHz");
4
170
    test_v.push_back("show");
4
171
    test_v.push_back("all");
4
172
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
173
    deleteSwitch("Aaa");
4
174
}
175
176
TEST_F(command433MHz_Class_fixture, addExistingWeather)
4
177
{
4
178
    test_v.push_back("show");
4
179
    test_v.push_back("all");
4
180
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
181
    auto v = test_rec.getWeather_StationPtrVector();
4
182
    EXPECT_EQ(v.size(),1);
4
183
    test_v.clear();
4
184
    test_v.push_back("433MHz");
4
185
    test_v.push_back("add");
4
186
    test_v.push_back("WEATHER");
4
187
    test_v.push_back("first");
4
188
    test_v.push_back("1234");
4
189
4
190
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
191
    v = test_rec.getWeather_StationPtrVector();
4
192
    EXPECT_EQ(v.size(),1);
4
193
    test_v.clear();
4
194
    test_v.push_back("433MHz");
4
195
    test_v.push_back("show");
4
196
    test_v.push_back("all");
4
197
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
198
}
199
200
TEST_F(command433MHz_Class_fixture, missingParamiter_addSwitch)
4
201
{
4
202
    test_v.push_back("show");
4
203
    test_v.push_back("all");
4
204
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
205
    auto v = test_rec.getSwitchPointerVector();
4
206
    EXPECT_EQ(v.size(),5);
4
207
    test_v.clear();
4
208
    test_v.push_back("433MHz");
4
209
    test_v.push_back("add");
4
210
    test_v.push_back("SWITCH");
4
211
    test_v.push_back("Abc");
4
212
    test_v.push_back("1234");
4
213
    test_v.push_back("onCode_A");
4
214
    test_v.push_back("ofCode_A");
4
215
    test_v.push_back("on15sec_A");
4
216
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
12
217
    EXPECT_THAT(result, testing::HasSubstr("mising paramiter")) << "nie ma bledu";
4
218
    v = test_rec.getSwitchPointerVector();
4
219
    EXPECT_EQ(v.size(),5);
4
220
    test_v.clear();
4
221
    test_v.push_back("433MHz");
4
222
    test_v.push_back("show");
4
223
    test_v.push_back("all");
4
224
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
225
}
226
\
227
TEST_F(command433MHz_Class_fixture, add_wrongType_addSwitch)
4
228
{
4
229
    test_v.push_back("show");
4
230
    test_v.push_back("all");
4
231
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
232
    auto v = test_rec.getSwitchPointerVector();
4
233
    EXPECT_EQ(v.size(),5);
4
234
    test_v.clear();
4
235
    test_v.push_back("433MHz");
4
236
    test_v.push_back("add");
4
237
    test_v.push_back("FAKE"); //here is wrong type
4
238
    test_v.push_back("Abc");
4
239
    test_v.push_back("1234");
4
240
    test_v.push_back("onCode_A");
4
241
    test_v.push_back("ofCode_A");
4
242
    test_v.push_back("on15sec_A");
4
243
    test_v.push_back("sunrise_A");
4
244
    test_v.push_back("sunset_A");
4
245
    test_v.push_back("lock_A");
4
246
    test_v.push_back("unlock_A");
4
247
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
4
248
    EXPECT_THAT(result, testing::HasSubstr("wrong type"));
4
249
    std::cout << "wynik testu: " << result << std::endl;
4
250
    v = test_rec.getSwitchPointerVector();
4
251
    EXPECT_EQ(v.size(),5);
4
252
    test_v.clear();
4
253
    test_v.push_back("433MHz");
4
254
    test_v.push_back("show");
4
255
    test_v.push_back("all");
4
256
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
257
}
258
259
TEST_F(command433MHz_Class_fixture, add_wrongID_addSwitch)
4
260
{
4
261
    test_v.push_back("show");
4
262
    test_v.push_back("all");
4
263
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
264
    auto v = test_rec.getSwitchPointerVector();
4
265
    EXPECT_EQ(v.size(),5);
4
266
    test_v.clear();
4
267
    test_v.push_back("433MHz");
4
268
    test_v.push_back("add");
4
269
    test_v.push_back("SWITCH");
4
270
    test_v.push_back("Abc");
4
271
    test_v.push_back("dummy"); //here is wrong ID
4
272
    test_v.push_back("onCode_A");
4
273
    test_v.push_back("ofCode_A");
4
274
    test_v.push_back("on15sec_A");
4
275
    test_v.push_back("sunrise_A");
4
276
    test_v.push_back("sunset_A");
4
277
    test_v.push_back("lock_A");
4
278
    test_v.push_back("unlock_A");
4
279
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
4
280
    std::cout << "wynik testu: " << result << std::endl;
4
281
    EXPECT_THAT(result, testing::HasSubstr("wrong ID"));
4
282
    v = test_rec.getSwitchPointerVector();
4
283
    EXPECT_EQ(v.size(),5);
4
284
    test_v.clear();
4
285
    test_v.push_back("433MHz");
4
286
    test_v.push_back("show");
4
287
    test_v.push_back("all");
4
288
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
289
}
290
291
TEST_F(command433MHz_Class_fixture, show_switch)
4
292
{
4
293
    test_v.push_back("show");
4
294
    test_v.push_back("all");
4
295
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
296
    auto v = test_rec.getSwitchPointerVector();
4
297
    EXPECT_EQ(v.size(),5);
4
298
    test_v.clear();
4
299
    test_v.push_back("433MHz");
4
300
    test_v.push_back("show");
4
301
    test_v.push_back("switch");
4
302
4
303
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
4
304
    std::cout << "wynik testu: " << result << std::endl;
4
305
    EXPECT_THAT(result, testing::HasSubstr("UNDEFINE"));
4
306
    v = test_rec.getSwitchPointerVector();
4
307
    EXPECT_EQ(v.size(),5);
4
308
    test_v.clear();
4
309
    test_v.push_back("433MHz");
4
310
    test_v.push_back("show");
4
311
    test_v.push_back("all");
4
312
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
313
}
314
315
TEST_F(command433MHz_Class_fixture, show_aether)
4
316
{
4
317
    test_my_data.main_RFLink->rflinkMAP["kk"].msg = "astro";
4
318
    test_my_data.main_RFLink->rflinkMAP["kk"].m_counter = 99;
4
319
    test_my_data.main_RFLink->rflinkMAP["jj"].msg = "lock";
4
320
    test_my_data.main_RFLink->rflinkMAP["jj"].m_counter = 155;
4
321
    test_v.push_back("show");
4
322
    test_v.push_back("all");
4
323
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
324
    auto v = test_rec.getSwitchPointerVector();
4
325
    EXPECT_EQ(v.size(),5);
4
326
    test_v.clear();
4
327
    test_v.push_back("433MHz");
4
328
    test_v.push_back("show");
4
329
    test_v.push_back("aether");
4
330
4
331
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
4
332
    std::cout << "wynik testu: " << result << std::endl;
4
333
    EXPECT_THAT(result, testing::HasSubstr("astro"));
4
334
    EXPECT_THAT(result, testing::HasSubstr("lock"));
4
335
    EXPECT_THAT(result, testing::HasSubstr("99"));
4
336
    EXPECT_THAT(result, testing::HasSubstr("155"));
4
337
    v = test_rec.getSwitchPointerVector();
4
338
    EXPECT_EQ(v.size(),5);
4
339
    test_v.clear();
4
340
}
341
342
TEST_F(command433MHz_Class_fixture, switchRF433)
4
343
{
4
344
    test_v.push_back("show");
4
345
    test_v.push_back("all");
4
346
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
347
    auto v = test_rec.getSwitchPointerVector();
4
348
    EXPECT_EQ(v.size(),5);
4
349
    /////////////////////////////// ON
4
350
    test_v.clear();
4
351
    test_v.push_back("433MHz");
4
352
    test_v.push_back("switch");
4
353
    test_v.push_back("B");
4
354
    test_v.push_back("ON");
4
355
    test_command_433MHz->execute(test_v,&test_my_data);
4
356
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::ON);
4
357
    ////////////////////////////// OFF
4
358
    test_v.clear();
4
359
    test_v.push_back("433MHz");
4
360
    test_v.push_back("switch");
4
361
    test_v.push_back("B");
4
362
    test_v.push_back("OFF");
4
363
    test_command_433MHz->execute(test_v,&test_my_data);
4
364
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::OFF);
4
365
    //////////////////////////////  15s
4
366
    test_v.clear();
4
367
    test_v.push_back("433MHz");
4
368
    test_v.push_back("switch");
4
369
    test_v.push_back("B");
4
370
    test_v.push_back("15s");
4
371
    test_command_433MHz->execute(test_v,&test_my_data);
4
372
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::WORKING);
4
373
    ////////////////////////////// unknown paramiter
4
374
    test_v.clear();
4
375
    test_v.push_back("433MHz");
4
376
    test_v.push_back("switch");
4
377
    test_v.push_back("B");
4
378
    test_v.push_back("fake");
4
379
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
4
380
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::WORKING);
4
381
    EXPECT_THAT(result, testing::HasSubstr("fake"));
4
382
    ///////////////////////////// fake switch
4
383
    test_v.clear();
4
384
    test_v.push_back("433MHz");
4
385
    test_v.push_back("switch");
4
386
    test_v.push_back("B_fake");
4
387
    test_v.push_back("fake");
4
388
4
389
    result = test_command_433MHz->execute(test_v,&test_my_data);
4
390
    EXPECT_THAT(result, testing::HasSubstr("not found"));
4
391
    v = test_rec.getSwitchPointerVector();
4
392
    EXPECT_EQ(v.size(),5);
4
393
    test_v.clear();
4
394
}
395
396
TEST_F(command433MHz_Class_fixture, sendRF433)
4
397
{
4
398
    test_v.push_back("show");
4
399
    test_v.push_back("all");
4
400
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
4
401
    auto v = test_rec.getSwitchPointerVector();
4
402
    EXPECT_EQ(v.size(),5);
4
403
    test_v.clear();
4
404
    test_v.push_back("433MHz");
4
405
    test_v.push_back("send");
4
406
    test_v.push_back("fake");
4
407
4
408
     std::string retStr = test_command_433MHz->execute(test_v,&test_my_data);
4
409
    EXPECT_THAT(retStr, testing::HasSubstr("sended"));
4
410
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/TEST/command_ardu_BT.cpp
1
#include <gtest/gtest.h>
2
#include "../command_ardu.h"
3
#include "../../../functions/functions.h"
4
#include "../../../RADIO_433_eq/radio_433_eq.h"
5
#include "../../../433MHz/RFLink/rflinkhandler.h"
6
#include "../../../iDomTools/test/iDomTools_fixture.h"
7
8
class commandArdu_Class_fixture : public iDomTOOLS_ClassTest
9
{
10
public:
44
11
    commandArdu_Class_fixture()  {
44
12
        this->test_RFLink = std::nullptr_t();
44
13
        this->test_ardu = std::nullptr_t();
44
14
    }
15
16
protected:
17
    std::vector<std::string> test_v= {"ardu"};
18
    RFLinkHandler* test_RFLink;
19
    blockQueue test_q;
20
    command_ardu* test_ardu;
21
    void SetUp() final
44
22
    {
44
23
        iDomTOOLS_ClassTest::SetUp();
44
24
44
25
        test_q._clearAll();
44
26
44
27
        test_RFLink = new RFLinkHandler(&test_my_data);
44
28
        test_ardu = new command_ardu("ardu", &test_my_data);
44
29
        test_my_data.main_RFLink = test_RFLink;
44
30
        test_v.push_back("433MHz");
44
31
        std::cout << "commandArdu_Class_fixture SetUp" << std::endl;
44
32
    }
33
34
    void TearDown() final
44
35
    {
44
36
        iDomTOOLS_ClassTest::TearDown();
44
37
        delete test_RFLink;
44
38
        delete test_ardu;
44
39
        std::cout << "commandArdu_Class_fixture TearDown" << std::endl;
44
40
    }
41
42
};
43
44
TEST_F(commandArdu_Class_fixture, wrongMSGformat)
4
45
{
4
46
    test_v.push_back("EV1527;ID=01e7be;SWITCH=01;CMD=ON;"); // wronh msg format missing 20;
4
47
    EXPECT_THROW(test_ardu->execute(test_v, &test_my_data), WRONG_FORMAT);
4
48
}
49
50
TEST_F(commandArdu_Class_fixture, UnlockHome)
4
51
{
4
52
    test_idomTOOLS->lockHome();
4
53
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
4
54
4
55
    test_v.push_back("20;EV1527;ID=01e7be;SWITCH=01;CMD=ON;");
4
56
    test_ardu->execute(test_v, &test_my_data);
4
57
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
4
58
4
59
    EXPECT_EQ(test_q._size(),1);
4
60
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
4
61
    EXPECT_EQ(test_q._size(),0);
4
62
}
63
64
TEST_F(commandArdu_Class_fixture, LockHome)
4
65
{
4
66
    test_idomTOOLS->unlockHome();
4
67
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
4
68
4
69
    test_v.push_back("20;EV1527;ID=01e7be;SWITCH=01;CMD=ON;");
12
70
    for(auto i : {1,2,3}){
12
71
        test_ardu->execute(test_v, &test_my_data);
12
72
    }
4
73
4
74
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
4
75
    EXPECT_EQ(test_q._size(),1);
4
76
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
4
77
    EXPECT_EQ(test_q._size(),0);
4
78
}
79
80
TEST_F(commandArdu_Class_fixture, playMusic)
4
81
{
4
82
    test_idomTOOLS->unlockHome();
4
83
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
4
84
    EXPECT_EQ(test_status.getObjectState("listwa"),STATE::UNKNOWN);
4
85
    test_status.addObject("music",STATE::STOP);
4
86
4
87
    test_v.push_back("20;EV1527;ID=01e7be;SWITCH=01;CMD=ON;");
4
88
4
89
    test_ardu->execute(test_v, &test_my_data);
4
90
4
91
    EXPECT_EQ(test_q._size(),1);
4
92
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
4
93
    EXPECT_EQ(test_q._size(),0);
4
94
    EXPECT_EQ(test_status.getObjectState("listwa"),STATE::ON);
4
95
}
96
97
TEST_F(commandArdu_Class_fixture, stopMusic)
4
98
{
4
99
    test_idomTOOLS->unlockHome();
4
100
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
4
101
    EXPECT_EQ(test_status.getObjectState("listwa"),STATE::UNKNOWN);
4
102
    test_status.addObject("music",STATE::PLAY);
4
103
4
104
    test_v.push_back("20;EV1527;ID=01e7be;SWITCH=01;CMD=ON;");
4
105
4
106
    test_ardu->execute(test_v, &test_my_data);
4
107
4
108
    EXPECT_EQ(test_q._size(),1);
4
109
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
4
110
    EXPECT_EQ(test_q._size(),0);
4
111
    EXPECT_EQ(test_status.getObjectState("listwa"),STATE::OFF);
4
112
}
113
114
TEST_F(commandArdu_Class_fixture, weatherStationTemp)
4
115
{
4
116
    test_v.push_back("20;2A;LaCrosse;ID=0704;TEMP=8043;");
4
117
    test_ardu->execute(test_v, &test_my_data);
4
118
    RADIO_WEATHER_STATION* st = static_cast<RADIO_WEATHER_STATION*>(test_my_data.main_REC->getEqPointer("first"));
4
119
    EXPECT_DOUBLE_EQ(-6.7, st->data.getTemperature() );
4
120
    EXPECT_DOUBLE_EQ(0, st->data.getHumidity() );
4
121
    test_v[2] = "20;35;LaCrosse;ID=0704;HUM=42;";
4
122
    test_ardu->execute(test_v, &test_my_data);
4
123
    EXPECT_DOUBLE_EQ(42, st->data.getHumidity() );
4
124
    test_v[2] = "20;2A;LaCrosse;ID=0704;TEMP=0000;";
4
125
    test_ardu->execute(test_v, &test_my_data);
4
126
    EXPECT_DOUBLE_EQ(0, st->data.getTemperature() );
4
127
}
128
129
TEST_F(commandArdu_Class_fixture, command_ardu_show)
4
130
{
4
131
    test_v.pop_back();
4
132
    test_v.push_back("show");
4
133
    std::string retStr = test_ardu->execute(test_v, &test_my_data);
4
134
    EXPECT_THAT(retStr, testing::HasSubstr("data: 0"));
4
135
    EXPECT_THAT(retStr, testing::HasSubstr("temperature= 0c"));
4
136
}
137
138
TEST_F(commandArdu_Class_fixture, command_ardu_help)
4
139
{
4
140
    command_ardu test_Command_ardu ("ardu");
4
141
4
142
    std::string retStr = test_Command_ardu.help();
4
143
    EXPECT_STREQ(retStr.c_str(), " only for internal usege\n");
4
144
}
145
146
TEST_F(commandArdu_Class_fixture, command_ardu_433MHz_throw)
4
147
{
4
148
    test_v.push_back("fake_msg");
4
149
    std::string retStr = test_ardu->execute(test_v, &test_my_data);
4
150
4
151
    EXPECT_THAT(retStr, testing::HasSubstr("for"));
4
152
}
153
154
TEST_F(commandArdu_Class_fixture, command_ardu_433MHz_OK)
4
155
{
4
156
    test_v.push_back("20;53;OK;");
4
157
    test_ardu->execute(test_v, &test_my_data);
4
158
    EXPECT_NE(test_my_data.main_RFLink->okTime, 0);
4
159
    EXPECT_EQ(test_my_data.main_RFLink->okTime, Clock::getUnixTime());
4
160
}
161
162
TEST_F(commandArdu_Class_fixture, command_ardu_433MHz_PING)
4
163
{
4
164
    test_v.push_back("20;99;PONG;");
4
165
    test_ardu->execute(test_v, &test_my_data);
4
166
    EXPECT_NE(test_my_data.main_RFLink->pingTime, 0);
4
167
    EXPECT_EQ(test_my_data.main_RFLink->pingTime, Clock::getUnixTime());
4
168
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/TEST/command_big_BT.cpp
1
#include "../command_big.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_big_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_big_Class_fixture()
4
8
    {
4
9
4
10
    }
11
12
protected:
13
    std::unique_ptr<command_big> test_command_big;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
4
17
    {
4
18
        iDomTOOLS_ClassTest::SetUp();
4
19
        test_command_big =  std::make_unique <command_big> ("big");
4
20
    }
21
22
    void TearDown() final
4
23
    {
4
24
        iDomTOOLS_ClassTest::TearDown();
4
25
    }
26
};
27
28
TEST_F(command_big_Class_fixture, main)
4
29
{
4
30
    int s = 55;
4
31
    test_v.push_back("big");
4
32
    test_v.push_back(std::to_string(s));
4
33
    auto ret = test_command_big->execute(test_v,&test_my_data);
4
34
    EXPECT_EQ(ret.size(),s);
4
35
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/TEST/command_hello_BT.cpp
1
#include "../command_hello.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_hello_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_hello_Class_fixture()
4
8
    {
4
9
4
10
    }
11
12
protected:
13
    std::unique_ptr<command_hello> test_command_hello;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
4
17
    {
4
18
        iDomTOOLS_ClassTest::SetUp();
4
19
        test_command_hello =  std::make_unique <command_hello> ("hello");
4
20
    }
21
22
    void TearDown() final
4
23
    {
4
24
        iDomTOOLS_ClassTest::TearDown();
4
25
    }
26
};
27
28
TEST_F(command_hello_Class_fixture, main)
4
29
{
4
30
    test_v.push_back("hello");
4
31
    auto ret = test_command_hello->execute(test_v,&test_my_data);
4
32
    EXPECT_STREQ(ret.c_str(),"\nHI You User!\n");
4
33
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/TEST/command_help_BT.cpp
1
#include "../command_help.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_help_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_help_Class_fixture()
8
8
    {
8
9
8
10
    }
11
12
protected:
13
    std::unique_ptr<command_help> test_command_help;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
8
17
    {
8
18
        iDomTOOLS_ClassTest::SetUp();
8
19
        test_command_help =  std::make_unique <command_help> ("help");
8
20
    }
21
22
    void TearDown() final
8
23
    {
8
24
        iDomTOOLS_ClassTest::TearDown();
8
25
    }
26
};
27
28
TEST_F(command_help_Class_fixture, all)
4
29
{
4
30
    commandHandlerRoot* chr = new commandHandlerRoot(&test_my_data);
4
31
    test_v.push_back("help");
4
32
    auto size = test_command_help->execute(test_v,&test_my_data).size();
4
33
    EXPECT_EQ(size,4376);
4
34
    delete chr;
4
35
}
36
37
TEST_F(command_help_Class_fixture, one)
4
38
{
4
39
    commandHandlerRoot* chr = new commandHandlerRoot(&test_my_data);
4
40
    test_v.push_back("help");
4
41
    test_v.push_back("ok");
4
42
    auto ret = test_command_help->execute(test_v,&test_my_data);
4
43
    EXPECT_STREQ(ret.c_str(),"ok - confirmation msg server response: END \n");
4
44
    delete chr;
4
45
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/TEST/command_idom_BT.cpp
1
#include <gtest/gtest.h>
2
3
#include "../command_idom.h"
4
#include "../../../functions/functions.h"
5
#include "../../../RADIO_433_eq/radio_433_eq.h"
6
#include "../../../433MHz/RFLink/rflinkhandler.h"
7
#include "../../../iDomTools/test/iDomTools_fixture.h"
8
#include "../../../thread_functions/iDom_thread.h"
9
10
class commandiDom_Class_fixture : public iDomTOOLS_ClassTest
11
{
12
public:
13
    commandiDom_Class_fixture()
80
14
    {
80
15
        this->test_command_iDom = std::nullptr_t();
80
16
        this->test_RFLink = std::nullptr_t();
80
17
    }
18
19
protected:
20
    std::vector<std::string> test_v= {"iDom"};
21
    RFLinkHandler* test_RFLink;
22
    blockQueue test_q;
23
    command_iDom* test_command_iDom;
24
25
    void SetUp() final
80
26
    {
80
27
        iDomTOOLS_ClassTest::SetUp();
80
28
80
29
        test_q._clearAll();
80
30
80
31
        test_RFLink = new RFLinkHandler(&test_my_data);
80
32
        test_command_iDom = new command_iDom("iDom");
80
33
        test_my_data.main_RFLink = test_RFLink;
80
34
        std::cout << "commandiDom_Class_fixture SetUp" << std::endl;
80
35
    }
36
37
    void TearDown() final
80
38
    {
80
39
        iDomTOOLS_ClassTest::TearDown();
80
40
        delete test_RFLink;
80
41
        delete test_command_iDom;
80
42
        std::cout << "commandiDom_Class_fixture TearDown" << std::endl;
80
43
    }
44
};
45
46
TEST_F(commandiDom_Class_fixture, getName)
4
47
{
4
48
    EXPECT_THAT(test_command_iDom->getCommandName(),testing::HasSubstr("iDom"));
4
49
}
50
51
TEST_F(commandiDom_Class_fixture, help)
4
52
{
4
53
    std::string helpStr = test_command_iDom->help();
4
54
    EXPECT_THAT(helpStr,testing::HasSubstr("iDom"));
4
55
    std::cout << "test " << helpStr.size() << std::endl;
4
56
    EXPECT_EQ(helpStr.size(),1189);
4
57
}
58
59
TEST_F(commandiDom_Class_fixture, less_param)
4
60
{
4
61
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
62
    EXPECT_THAT(retStr,testing::HasSubstr("need parameter!"));
4
63
}
64
TEST_F(commandiDom_Class_fixture, unknonw_para)
4
65
{
4
66
    test_v.push_back("fake");
4
67
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
68
    EXPECT_THAT(retStr,testing::HasSubstr("iDom - unknown parameter:"));
4
69
}
70
71
TEST_F(commandiDom_Class_fixture, speakers)
4
72
{
4
73
    test_my_data.main_iDomTools->unlockHome();
4
74
    //////////////// fake command
4
75
    test_v.push_back("speakers");
4
76
    test_v.push_back("fake");
4
77
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
78
    EXPECT_THAT(retStr,testing::HasSubstr("unknow speakers action: fake"));
4
79
    ///////////////// ON
4
80
    test_my_data.main_iDomStatus->setObjectState("speakers",STATE::UNDEFINE);
4
81
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::UNDEFINE);
4
82
    test_v.clear();
4
83
    test_v.push_back("iDom");
4
84
    test_v.push_back("speakers");
4
85
    test_v.push_back("ON");
4
86
    retStr = test_command_iDom->execute(test_v, &test_my_data);
4
87
    EXPECT_THAT(retStr,testing::HasSubstr("speakers ON"));
4
88
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::ON);
4
89
    ///////////////// OFF
4
90
    test_v.clear();
4
91
    test_v.push_back("iDom");
4
92
    test_v.push_back("speakers");
4
93
    test_v.push_back("OFF");
4
94
    retStr = test_command_iDom->execute(test_v, &test_my_data);
4
95
    EXPECT_THAT(retStr,testing::HasSubstr("speakers OFF"));
4
96
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::OFF);
4
97
}
98
99
TEST_F(commandiDom_Class_fixture, sunset_sunrise)
4
100
{
4
101
    test_v.clear();
4
102
    test_v.push_back("iDom");
4
103
    test_v.push_back("sunset");
4
104
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
105
    std::cout << "retString: " << retStr << std::endl;
4
106
    EXPECT_THAT(retStr,testing::HasSubstr("Sunset time:"));
4
107
4
108
    test_v.clear();
4
109
    test_v.push_back("iDom");
4
110
    test_v.push_back("sunrise");
4
111
    retStr = test_command_iDom->execute(test_v, &test_my_data);
4
112
    std::cout << "retString: " << retStr << std::endl;
4
113
    EXPECT_THAT(retStr,testing::HasSubstr("Sunrise time:"));
4
114
}
115
116
TEST_F(commandiDom_Class_fixture, day_lenght)
4
117
{
4
118
    test_v.clear();
4
119
    test_v.push_back("iDom");
4
120
    test_v.push_back("day");
4
121
    test_v.push_back("lenght");
4
122
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
123
    std::cout << "retString: " << retStr << std::endl;
4
124
    EXPECT_THAT(retStr,testing::HasSubstr("Day Lenght :"));
4
125
}
126
127
TEST_F(commandiDom_Class_fixture, sun)
4
128
{
4
129
    test_v.clear();
4
130
    test_v.push_back("iDom");
4
131
    test_v.push_back("sun");
4
132
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
133
    std::cout << "retString: " << retStr << std::endl;
4
134
    EXPECT_THAT(retStr,testing::HasSubstr("Day Lenght :"));
4
135
}
136
137
TEST_F(commandiDom_Class_fixture, sysinfo)
4
138
{
4
139
    test_v.clear();
4
140
    test_v.push_back("iDom");
4
141
    test_v.push_back("sysinfo");
4
142
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
143
    std::cout << "retString: " << retStr << std::endl;
4
144
    EXPECT_THAT(retStr,testing::HasSubstr("free RAM"));
4
145
}
146
147
TEST_F(commandiDom_Class_fixture, temperature)
4
148
{
4
149
    TEST_DATA::return_send_to_arduino = "-12:22";
4
150
    test_v.clear();
4
151
    test_v.push_back("iDom");
4
152
    test_v.push_back("temperature");
4
153
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
154
    std::cout << "retString: " << retStr << std::endl;
4
155
    EXPECT_THAT(retStr,testing::HasSubstr("-12:22"));
4
156
4
157
    test_v.clear();
4
158
    test_v.push_back("iDom");
4
159
    test_v.push_back("temperature");
4
160
    test_v.push_back("stats");
4
161
    test_v.push_back("insideee");
4
162
    retStr = test_command_iDom->execute(test_v, &test_my_data);
4
163
    std::cout << "retString: " << retStr << std::endl;
4
164
    EXPECT_THAT(retStr,testing::HasSubstr("not found!"));
4
165
}
166
167
TEST_F(commandiDom_Class_fixture, text)
4
168
{
4
169
    TEST_DATA::return_send_to_arduino = "-12:22";
4
170
    test_v.clear();
4
171
    test_v.push_back("iDom");
4
172
    test_v.push_back("text");
4
173
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
174
    std::cout << "retString: " << retStr << std::endl;
4
175
    EXPECT_THAT(retStr,testing::HasSubstr("Godzina"));
4
176
}
177
178
TEST_F(commandiDom_Class_fixture, lock_unlock)
4
179
{
4
180
    test_v.clear();
4
181
    test_v.push_back("iDom");
4
182
    test_v.push_back("lock");
4
183
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
184
    std::cout << "retString: " << retStr << std::endl;
4
185
    EXPECT_EQ(test_my_data.idom_all_state.houseState, STATE::LOCK);
4
186
4
187
    test_v.clear();
4
188
    test_v.push_back("iDom");
4
189
    test_v.push_back("unlock");
4
190
    retStr = test_command_iDom->execute(test_v, &test_my_data);
4
191
    std::cout << "retString: " << retStr << std::endl;
4
192
    EXPECT_EQ(test_my_data.idom_all_state.houseState, STATE::UNLOCK);
4
193
}
194
195
TEST_F(commandiDom_Class_fixture, t_230V)
4
196
{
4
197
    test_my_data.main_iDomTools->unlockHome();
4
198
    //////////////// fake command
4
199
    test_v.push_back("230V");
4
200
    test_v.push_back("fake");
4
201
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
202
    EXPECT_THAT(retStr,testing::HasSubstr("wrong paramiter"));
4
203
    ///////////////// ON
4
204
    test_my_data.main_iDomStatus->setObjectState("printer",STATE::UNDEFINE);
4
205
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("printer"), STATE::UNDEFINE);
4
206
    test_v.clear();
4
207
    test_v.push_back("iDom");
4
208
    test_v.push_back("230V");
4
209
    test_v.push_back("ON");
4
210
    retStr = test_command_iDom->execute(test_v, &test_my_data);
4
211
    std::cout << "retString: " << retStr << std::endl;
4
212
    EXPECT_THAT(retStr,testing::HasSubstr("230V ON"));
4
213
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("printer"), STATE::ON);
4
214
    ///////////////// OFF
4
215
    test_v.clear();
4
216
    test_v.push_back("iDom");
4
217
    test_v.push_back("230V");
4
218
    test_v.push_back("OFF");
4
219
    retStr = test_command_iDom->execute(test_v, &test_my_data);
4
220
    std::cout << "retString: " << retStr << std::endl;
4
221
    EXPECT_THAT(retStr,testing::HasSubstr("230V OFF"));
4
222
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("printer"), STATE::OFF);
4
223
}
224
225
TEST_F(commandiDom_Class_fixture, smog)
4
226
{
4
227
    test_v.clear();
4
228
    test_v.push_back("iDom");
4
229
    test_v.push_back("smog");
4
230
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
231
    std::cout << "retString: " << retStr << std::endl;
4
232
    EXPECT_THAT(retStr,testing::HasSubstr(" mg/m^3"));
4
233
}
234
235
TEST_F(commandiDom_Class_fixture, say)
4
236
{
4
237
    Clock::setTime_forBT_usage(23,23);
4
238
    TEST_DATA::return_send_to_arduino = "-3:6";
4
239
    test_v.clear();
4
240
    test_v.push_back("iDom");
4
241
    test_v.push_back("say");
4
242
    test_v.push_back("dummy");
4
243
    test_v.push_back("dummy");
4
244
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
245
    std::cout << "retString: " << retStr << std::endl;
4
246
    //EXPECT_THAT(retStr,testing::HasSubstr("sad"));
4
247
}
248
TEST_F(commandiDom_Class_fixture, wifi)
4
249
{
4
250
    TEST_DATA::return_httpPost = "ok";
4
251
    test_v.clear();
4
252
    test_v.push_back("iDom");
4
253
    test_v.push_back("wifi");
4
254
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
255
    std::cout << "retString: " << retStr << std::endl;
4
256
    EXPECT_THAT(retStr,testing::HasSubstr("ok"));
4
257
}
258
259
TEST_F(commandiDom_Class_fixture, lightning)
4
260
{
4
261
    test_v.clear();
4
262
    test_v.push_back("iDom");
4
263
    test_v.push_back("lightning");
4
264
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
265
    std::cout << "retString: " << retStr << std::endl;
4
266
    EXPECT_THAT(retStr,testing::HasSubstr("bool: "));
4
267
}
268
269
TEST_F(commandiDom_Class_fixture, camera)
4
270
{
4
271
    test_my_data.server_settings->cameraLedOFF = "cameraOFF";
4
272
    test_my_data.server_settings->cameraLedON = "cameraON";
4
273
4
274
    Clock::setTime_forBT_usage(23,23);
4
275
    test_v.clear();
4
276
    test_v.push_back("iDom");
4
277
    test_v.push_back("camera");
4
278
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
279
    std::cout << "retString: " << retStr << std::endl;
4
280
    EXPECT_STREQ(retStr.c_str(),"not enough parameters");
4
281
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"),STATE::UNKNOWN);
4
282
    ////////////////////////////////////////// ON
4
283
    TEST_DATA::return_httpPost = "ok.\n";
4
284
    test_v.clear();
4
285
    test_v.push_back("iDom");
4
286
    test_v.push_back("camera");
4
287
    test_v.push_back("LED");
4
288
4
289
    test_v.push_back("ON");
4
290
    retStr = test_command_iDom->execute(test_v, &test_my_data);
4
291
    std::cout << "retString: " << retStr << std::endl;
4
292
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"),STATE::ON);
4
293
    EXPECT_STREQ(retStr.c_str(),"led DONE");
4
294
    ////////////////////////////////////////// OFF
4
295
    TEST_DATA::return_httpPost = "ok.\n";
4
296
    test_v.clear();
4
297
    test_v.push_back("iDom");
4
298
    test_v.push_back("camera");
4
299
    test_v.push_back("LED");
4
300
4
301
    test_v.push_back("OFF");
4
302
    retStr = test_command_iDom->execute(test_v, &test_my_data);
4
303
    std::cout << "retString: " << retStr << std::endl;
4
304
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"),STATE::OFF);
4
305
    EXPECT_STREQ(retStr.c_str(),"led DONE");
4
306
}
307
308
TEST_F(commandiDom_Class_fixture, LED)
4
309
{
4
310
    test_my_data.main_iDomTools->unlockHome();
4
311
4
312
    test_v.clear();
4
313
    test_v.push_back("iDom");
4
314
    test_v.push_back("LED");
4
315
    test_v.push_back("33");
4
316
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
317
    std::cout << "retString: " << retStr << std::endl;
4
318
    EXPECT_THAT(retStr,testing::HasSubstr("need more parameter from-to-R-G-B"));
4
319
4
320
    ///////////////////////////////////// OFF
4
321
    TEST_DATA::return_send_to_arduino = "led OFF";
4
322
4
323
    test_v.clear();
4
324
    test_v.push_back("iDom");
4
325
    test_v.push_back("LED");
4
326
    test_v.push_back("OFF");
4
327
    retStr = test_command_iDom->execute(test_v, &test_my_data);
4
328
    std::cout << "retString: " << retStr << std::endl;
4
329
    EXPECT_THAT(retStr,testing::HasSubstr("led OFF"));
4
330
}
331
TEST_F(commandiDom_Class_fixture, kodi)
4
332
{
4
333
    test_my_data.main_iDomStatus->setObjectState("KODI",STATE::ACTIVE);
4
334
    test_v.clear();
4
335
    test_v.push_back("iDom");
4
336
    test_v.push_back("KODI");
4
337
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
4
338
4
339
    std::cout << "retString: " << retStr << std::endl;
4
340
    EXPECT_STREQ(retStr.c_str(),"kodi already run");
4
341
4
342
    test_my_data.main_iDomStatus->setObjectState("KODI",STATE::DEACTIVE);
4
343
    test_my_data.main_iDomStatus->setObjectState("music",STATE::PLAY);
4
344
    test_my_data.main_iDomStatus->setObjectState("speakers",STATE::ON);
4
345
4
346
    std::array<Thread_array_struc,iDomConst::MAX_CONNECTION> test_ThreadArrayStruc;
4
347
44
348
    for (int i = 0 ; i < iDomConst::MAX_CONNECTION; i++)
40
349
        test_ThreadArrayStruc.at(i).thread_socket = i+1;
4
350
    test_ThreadArrayStruc.at(3).thread_socket = 0;
4
351
    test_my_data.main_THREAD_arr = &test_ThreadArrayStruc;
4
352
4
353
    test_v.clear();
4
354
    test_v.push_back("iDom");
4
355
    test_v.push_back("KODI");
4
356
    retStr = test_command_iDom->execute(test_v, &test_my_data);
4
357
4
358
    sleep(1);
4
359
    std::cout << "retString: " << retStr << std::endl;
4
360
    EXPECT_THAT(retStr,testing::HasSubstr("STARTED"));
4
361
44
362
    for (int i = 0 ; i < iDomConst::MAX_CONNECTION; i++)
40
363
        test_ThreadArrayStruc[i].thread_socket = -1;
4
364
    test_v.clear();
4
365
    test_v.push_back("iDom");
4
366
    test_v.push_back("KODI");
4
367
    retStr = test_command_iDom->execute(test_v, &test_my_data);
4
368
4
369
    std::cout << "retString: " << retStr << std::endl;
4
370
    EXPECT_STREQ(retStr.c_str(),"not free space to new thread");
4
371
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/TEST/command_ip_BT.cpp
1
#include "../command_ip.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_ip_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_ip_Class_fixture()
4
8
    {
4
9
4
10
    }
11
12
protected:
13
    std::unique_ptr<command_ip> test_command_ip;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
4
17
    {
4
18
        iDomTOOLS_ClassTest::SetUp();
4
19
        test_command_ip =  std::make_unique <command_ip> ("ip");
4
20
    }
21
22
    void TearDown() final
4
23
    {
4
24
        iDomTOOLS_ClassTest::TearDown();
4
25
    }
26
};
27
28
TEST_F(command_ip_Class_fixture, main)
4
29
{
4
30
    test_my_data.server_settings->SERVER_IP = "100.001.1.0";
4
31
    test_v.push_back("ip");
4
32
    auto ret = test_command_ip->execute(test_v,&test_my_data);
4
33
    EXPECT_STREQ(ret.c_str(),"iDom server IP: 100.001.1.0");
4
34
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/TEST/command_ok_BT.cpp
1
#include "../command_ok.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_ok_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_ok_Class_fixture()
4
8
    {
4
9
4
10
    }
11
12
protected:
13
    std::unique_ptr<command_ok> test_command_ok;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
4
17
    {
4
18
        iDomTOOLS_ClassTest::SetUp();
4
19
        test_command_ok =  std::make_unique <command_ok> ("ok");
4
20
    }
21
22
    void TearDown() final
4
23
    {
4
24
        iDomTOOLS_ClassTest::TearDown();
4
25
    }
26
};
27
28
TEST_F(command_ok_Class_fixture, main)
4
29
{
4
30
    test_v.push_back("ok");
4
31
    auto ret = test_command_ok->execute(test_v,&test_my_data);
4
32
    EXPECT_STREQ(ret.c_str(),"\nEND\n");
4
33
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_433mhz.cpp
1
#include "command_433mhz.h"
2
#include "../../RADIO_433_eq/radio_433_eq.h"
3
#include "../../433MHz/RFLink/rflinkhandler.h"
4
5
command_433MHz::command_433MHz(const std::string &name):command(name)
72
6
{
72
7
}
8
9
command_433MHz::~command_433MHz()
72
10
{
72
11
    // puts("command_433MHz::~command_433MHz()");
72
12
}
13
14
std::string command_433MHz::execute(std::vector<std::string> &v, thread_data *my_data)
160
15
{
160
16
    std::string str_buf = "wrong paramiter\n" + help();
160
17
    if (v.size() > 2){
160
18
        //////////////////////////// switch
160
19
        if (v[1] == "show" && v[2] == "all"){
84
20
            str_buf = my_data->main_REC->listAllName();
84
21
        }
76
22
        else if (v[1] == "delete" && v.size() == 3)
16
23
        {
16
24
            if (my_data->main_REC->nameExist(v[2]) == false)
4
25
            {
4
26
                return "equipment "+ v[2]+" not exist ";
4
27
            }
12
28
            my_data->main_REC->deleteRadioEq(v[2]);
12
29
            str_buf = v[2] + " deleted";
12
30
        }
60
31
        else if (v[1] == "add" && v.size() > 3) //zmień tu
28
32
        {
28
33
            RADIO_EQ_CONFIG cfg;
28
34
           /* if(v[2] == "SWITCH" && v.size() == 12)
28
35
                cfg.set(v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); // zmień tu
28
36
            else*/ if(v[2] == "BUTTON" && v.size() >= 6)
4
37
                cfg.set(v[2],v[3],v[4],v[5],v[6]); // zmień tu
24
38
            else if(v[2] == "WEATHER" && v.size() >= 4)
4
39
                cfg.set(v[2],v[3],v[4]); // zmień tu
24
40
            else
20
41
            {
20
42
                if (v.size() != 12)
4
43
                    return "mising paramiter!";
16
44
                cfg.set(v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); // zmień tu
16
45
                //return v[2] + " " + v[3] + " " + v[4] + "add more paramiter or wrong type";
16
46
}
28
47
            /////////////////////////////////////////////////////////////
24
48
            if (my_data->main_REC->nameExist(v[3]) == true)
4
49
            {
4
50
                return "equipment "+ v[3]+" exist ";
4
51
            }
20
52
            try
20
53
            {
20
54
                my_data->main_REC->addRadioEq(cfg,v[2]);
20
55
            }
20
56
            catch(const WRONG_FORMAT& )
4
57
            {
4
58
                return "wrong type "+v[2];
4
59
            }
20
60
            catch(const std::invalid_argument& )
4
61
            {
4
62
                return "wrong ID "+v[4];
4
63
            }
20
64
12
65
            str_buf = v[2] + " " + v[3] + " added";
12
66
            my_data->main_REC->saveConfig(my_data->server_settings->radio433MHzConfigFile);
12
67
        }
32
68
        else if (v[1] == "show" && v[2] == "switch"){
4
69
            str_buf = "";
4
70
            for (auto m_switch : my_data->main_REC->getSwitchPointerVector())
20
71
            {
20
72
                str_buf.append(stateToString(m_switch->getState()) );
20
73
            }
4
74
        }
28
75
        else if (v[1] == "show" && v[2] == "aether"){
4
76
            str_buf.clear();
4
77
            for(auto itr = my_data->main_RFLink->rflinkMAP.begin();
12
78
                itr != my_data->main_RFLink->rflinkMAP.end();
8
79
                itr++)
8
80
            {
8
81
                str_buf += itr->second.read();
8
82
                str_buf += '\n';
8
83
            }
4
84
            str_buf += ".";
4
85
4
86
        }
24
87
        else if (v[1] == "send"){
4
88
            str_buf = "sended!;";
4
89
            my_data->main_RFLink->sendCommand(v[2]);
4
90
4
91
        }
20
92
        else if (v[1] == "switch"){
20
93
            try{
20
94
                RADIO_SWITCH *m_switch = dynamic_cast<RADIO_SWITCH*>(my_data->main_REC->getEqPointer(v[2]));
20
95
20
96
                if (v[3] == "ON") {
4
97
                    m_switch->on();
4
98
                    str_buf = " done ";
4
99
                }
16
100
                else if (v[3] == "OFF"){
4
101
                    m_switch->off();
4
102
                    str_buf = " done ";
4
103
                }
12
104
                else if (v[3] == "15s"){
4
105
                    m_switch->onFor15sec();
4
106
                    str_buf = " done ";
4
107
                }
8
108
                else{
8
109
                    str_buf = "unknown paramiter: ";
8
110
                    str_buf.append(v[3]);
8
111
                }
20
112
            }
4
113
            catch (std::string& error){
4
114
                str_buf = error;
4
115
            }
20
116
            my_data->main_iDomTools->saveState_iDom();
20
117
        }
160
118
        /////////////////////////////////////////////
160
119
    }
140
120
    return str_buf;
160
121
}
122
123
std::string command_433MHz::help()
164
124
{
164
125
    std::stringstream help;
164
126
    help << ("433MHz delete <name> - dalete radio equipment") <<std::endl;
164
127
    help << ("433MHz add <type> <name> <ID> <onCode> <offCode> <on15sec> <sunrise> <sunset> <lock> <unlock> - add radio equipment") <<std::endl;
164
128
    help << ("433MHz switch <name> ON/OFF/15s - change switch state") <<std::endl;
164
129
    help << ("433MHz show all - list all equipment by name") <<std::endl;
164
130
    help << ("433MHz show aether - show aether devices by ID") <<std::endl;
164
131
    help << ("433MHz send <msg> - send command") <<std::endl;
164
132
    return help.str();
164
133
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_ardu.cpp
1
#include "command_ardu.h"
2
3
command_ardu::command_ardu(const std::string &name):command(name)
4
4
{
4
5
    this->m_mainRadioButton = std::nullptr_t();
4
6
}
7
8
command_ardu::command_ardu(const std::string& name, thread_data *my_data):command(name)
9
  ,m_button433MHzVector(my_data->main_REC->getButtonPointerVector())
64
10
{
64
11
    //m_button433MHzVector = my_data->main_REC->getButtonPointerVector();
64
12
    m_mainRadioButton = static_cast<RADIO_BUTTON*>(my_data->main_REC->getEqPointer("locker"));
64
13
64
14
    m_weatherStVe = my_data->main_REC->getWeather_StationPtrVector();
64
15
    m_mainWeatherStation = static_cast<RADIO_WEATHER_STATION*>(my_data->main_REC->getEqPointer("first"));
64
16
}
17
18
std::string command_ardu::execute(std::vector<std::string> &v, thread_data *my_data)
56
19
{
56
20
    std::string str_buf = " only for internal usage!";
56
21
    if (v.size() > 1){
56
22
        if(v[1] == "show"){
4
23
            RADIO_WEATHER_STATION* st = static_cast<RADIO_WEATHER_STATION*>(my_data->main_REC->getEqPointer("first"));
4
24
            str_buf = st->data.getDataString();
4
25
        }
56
26
        if(v[1] == "433MHz"){
52
27
            my_data->myEventHandler.run("433MHz")->addEvent("RFLink: "+v[2]);
52
28
            try {
52
29
                my_data->main_RFLink->
52
30
                        rflinkMAP[my_data->main_RFLink->getArgumentValueFromRFLinkMSG(v[2],
52
31
                        "ID")].counter();
52
32
                my_data->main_RFLink->
52
33
                        rflinkMAP[my_data->main_RFLink->getArgumentValueFromRFLinkMSG(v[2],
52
34
                        "ID")].msg = v[2];
52
35
            }
12
36
            catch(const std::string& e){
12
37
                std::cout << "wyjatek w szukaniu: " << e <<std::endl;
12
38
                pingAndOkRecv( my_data, v[2]);
12
39
            }
52
40
            //TODO add command
48
41
            try {
48
42
                if (m_mainRadioButton->getID() == my_data->main_RFLink->getArgumentValueFromRFLinkMSG(v[2],"ID") )
24
43
                {
24
44
                    my_data->main_iDomTools->button433mhzLockerPressed(m_mainRadioButton);
24
45
                }
48
46
            }
12
47
            catch (const std::string& e){ }
48
48
            try {
48
49
                if (m_mainWeatherStation->getID() == my_data->main_RFLink->getArgumentValueFromRFLinkMSG(v[2],"ID") )
12
50
                {
12
51
                    m_mainWeatherStation->data.putData(v[2]);
12
52
                }
48
53
            }
12
54
            catch (std::string& e){ }
48
55
        }
56
56
    }
52
57
    return str_buf;
56
58
}
59
60
std::string command_ardu::help()
8
61
{
8
62
    return " only for internal usege\n";
8
63
}
64
65
void command_ardu::pingAndOkRecv(thread_data *my_data, const std::string& s)
12
66
{
12
67
    if (s.find("OK;") != std::string::npos)
4
68
        my_data->main_RFLink->okTime = Clock::getUnixTime();
8
69
    else if (s.find("PONG;") != std::string::npos)
4
70
        my_data->main_RFLink->pingTime = Clock::getUnixTime();
12
71
    std::cout << "poing && ok recv " << s <<std::endl
12
72
              << " ok time: "<<my_data->main_RFLink->okTime<< std::endl
12
73
              << " ping time: "<<my_data->main_RFLink->pingTime<< std::endl;
12
74
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_big.cpp
1
#include "command_big.h"
2
3
command_big::command_big(const std::string &name):command(name)
24
4
{
24
5
24
6
}
7
8
std::string command_big::execute(std::vector<std::string> &v, thread_data *my_data)
4
9
{
4
10
    std::string str_buf = "command big - wrong paramiter:\n "+ help();
4
11
    if (v.size() > 1){
4
12
        str_buf.erase();
220
13
        for (int i =0; i < std::stoi(v[1])-1; ++i){
216
14
            str_buf += "z";
216
15
        }
4
16
        str_buf += "Y";
4
17
    }
4
18
    return str_buf;
4
19
}
20
21
std::string command_big::help()
8
22
{
8
23
    return "big <number> - send big (number) data \n";
8
24
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_clock.cpp
1
#include "command_clock.h"
2
#include "../../src/functions/functions.h"
3
4
command_clock::command_clock(const std::string &name):command(name)
20
5
{
20
6
20
7
}
8
9
std::string command_clock::execute(std::vector<std::string> &v, thread_data *my_data)
0
10
{
0
11
    if (v.size() > 1){
0
12
        return "clock set "+ useful_F::send_to_arduino_clock(my_data,v[1]);
0
13
    }
0
14
    return "can not set clock";
0
15
}
16
17
std::string command_clock::help()
4
18
{
4
19
    return "clock <number/string> - put number/string (max 4 digits) to 7segment LCD\n";
4
20
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_cmd.cpp
1
#include "command_cmd.h"
2
#include "../../src/functions/functions.h"
3
4
command_cmd::command_cmd(const std::string &name):command(name)
20
5
{
20
6
20
7
}
8
9
std::string command_cmd::execute(std::vector<std::string> &v, thread_data *my_data)
0
10
{
0
11
    if (v.size() == 1){
0
12
        return "fifo file contain: "+ useful_F_libs::read_from_mkfifo(my_data->server_settings->omxplayerFile);
0
13
    }
0
14
    return "error: unknown parameter: "+v[1];
0
15
}
16
17
std::string command_cmd::help()
4
18
{
4
19
    return "cmd - read char prom cmd fifo file for unblock video player\n";
4
20
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_event.cpp
1
#include "command_event.h"
2
3
command_event::command_event(const std::string &name) :command(name)
20
4
{
20
5
20
6
}
7
8
std::string command_event::execute(std::vector<std::string> &v, thread_data *my_data)
0
9
{
0
10
    if (v.size() == 1){
0
11
        return my_data->myEventHandler.getListPossibleEvents();
0
12
    }
0
13
    if (v.size() == 2){
0
14
        return my_data->myEventHandler.run(v[1])->getEvent();
0
15
    }
0
16
    if (v.size() == 3 && v[2]=="clear"){
0
17
        my_data->myEventHandler.run(v[1])->clearEvent();
0
18
        return "event " +v[1]+ " has been cleared!";
0
19
    }
0
20
    if (v.size() == 3 && v[2]=="intensity"){
0
21
        std::stringstream intensity;
0
22
        intensity << my_data->myEventHandler.run(v[1])->getLast1minNumberEvent();
0
23
        return "event " +v[1]+" "+ intensity.str() +" intensity per last minute!";
0
24
    }
0
25
    if (v.size() == 5 && v[2]=="clear"){
0
26
        unsigned int from = std::stoi(v[3]);
0
27
        unsigned int to = std::stoi(v[4]);
0
28
        my_data->myEventHandler.run(v[1])->clearEvent(from, to);
0
29
        return "event " +v[1]+ " has been cleared!";
0
30
    }
0
31
    return my_data->myEventHandler.help();
0
32
}
33
34
std::string command_event::help()
4
35
{
4
36
    std::stringstream help;
4
37
    help << "event- show actual event (all)" << std::endl;
4
38
    help << "event <name> - show one event" << std::endl;
4
39
    help << "event <name> clear - clear event <name>" << std::endl;
4
40
    help << "event <name> intensity - intensity per minute" <<std::endl;
4
41
    return help.str();
4
42
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_hello.cpp
1
#include "command_hello.h"
2
3
command_hello::command_hello(const std::string &name):command(name)
24
4
{
24
5
}
6
7
command_hello::~command_hello()
24
8
{
24
9
}
10
11
std::string command_hello::execute(std::vector<std::string> &v, thread_data *my_data)
4
12
{
4
13
    return "\nHI You User!\n";
4
14
}
15
16
std::string command_hello::help()
4
17
{
4
18
    return "hello - send test message to server if connection is ok, the server response: \"HI!\"\n";
4
19
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_help.cpp
1
#include "command_help.h"
2
#include <vector>
3
#include <algorithm>
4
5
command_help::command_help(const std::string &name):command(name)
28
6
{
28
7
puts("dupa command_help");
28
8
}
9
10
std::string command_help::execute(std::vector<std::string> &v, thread_data *my_data)
8
11
{
8
12
    std::string result ="";
8
13
    if (v.size() ==2){
4
14
4
15
        if (my_data->commandMapPtr->find(v[1]) == my_data->commandMapPtr->end()){
0
16
            return "unknown command: "+ v[1]+" help note not found";
0
17
        }
4
18
        else{
4
19
            return my_data->commandMapPtr->find(v[1])->second->help();
4
20
        }
4
21
    }
8
22
    else
4
23
    {
92
24
        for( auto iter= my_data->commandMapPtr->begin();iter != my_data->commandMapPtr->end(); ++iter ) {
88
25
88
26
            result+= iter->second->help();
88
27
            result+= "------------------------------------\n";
88
28
        }
4
29
    }
4
30
    return result;
8
31
}
32
33
std::string command_help::help()
4
34
{
4
35
    return "help - show help for all command \nhelp <parameter> - show help for command\n";
4
36
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_idom.cpp
1
#include "command_idom.h"
2
#include "../../functions/functions.h"
3
4
command_iDom::command_iDom(const std::string &name):command(name)
100
5
{
100
6
}
7
8
std::string command_iDom::execute(std::vector<std::string> &v, thread_data *my_data)
120
9
{
120
10
    if (v.size()<2){
4
11
        return "need parameter!\n" + help();
4
12
    }
116
13
    if (v[1]=="speakers")
12
14
    {
12
15
        if (v[2] =="ON"){
4
16
            iDomTOOLS::turnOnSpeakers();
4
17
            return "speakers ON";
4
18
        }
8
19
        else if (v[2]=="OFF"){
4
20
            iDomTOOLS::turnOffSpeakers();
4
21
            return "speakers OFF";
4
22
        }
4
23
        else{
4
24
            return "unknow speakers action: "+v[2];
4
25
        }
12
26
    }
104
27
    else if (v[1]=="sunset"){
4
28
        return my_data->main_iDomTools->getSunset(true);
4
29
    }
100
30
    else if (v[1]=="sunrise"){
4
31
        return my_data->main_iDomTools->getSunrise(true);
4
32
    }
96
33
    else if (v[1]=="day" && v[2]=="lenght"){
4
34
        return my_data->main_iDomTools->getDayLenght(true);
4
35
    }
92
36
    else if (v[1]=="sun"){
4
37
        std::string ret;
4
38
        ret = my_data->main_iDomTools->getSunrise(true);
4
39
        ret.append("\n");
4
40
        ret.append(my_data->main_iDomTools->getSunset(true));
4
41
        ret.append("\n");
4
42
        ret.append(my_data->main_iDomTools->getDayLenght(true));
4
43
        ret.append("\n");
4
44
        return ret;
4
45
    }
88
46
    else if (v[1]=="sysinfo"){
4
47
        return my_data->main_iDomTools->getSystemInfo();
4
48
    }
84
49
    else if (v[1]=="temperature"){
8
50
        if ( v.size() < 3){
4
51
            return my_data->main_iDomTools->getTemperatureString();
4
52
        }
4
53
        else {
4
54
            if (v[2] == "stats"){
4
55
                std::string ret;
4
56
                try{
4
57
                 ret = my_data->main_iDomTools->getThermoStats(v[3]);
4
58
                }
4
59
                catch (std::string& obj){
4
60
                    ret = obj +" "+v[3];
4
61
                }
4
62
               return ret;
4
63
            }
4
64
        }
8
65
    }
76
66
    else if (v[1]=="text"){
4
67
        return my_data->main_iDomTools->getTextToSpeach();
4
68
    }
72
69
    else if (v[1] == "lock"){
4
70
        my_data->main_iDomTools->lockHome();
4
71
        return "hous locked";
4
72
    }
68
73
    else if (v[1] == "unlock"){
4
74
        my_data->main_iDomTools->unlockHome();
4
75
        return "hous unlocked";
4
76
    }
64
77
    else if (v[1]=="LED"){
8
78
        if (v.size() != 7){
8
79
            if (v[2]=="OFF"){
4
80
                return my_data->main_iDomTools->ledOFF();
4
81
            }
4
82
            else if(v[2] == "set"){
0
83
               return my_data->main_iDomTools->ledOn(
0
84
                            my_data->ptr_pilot_led->colorLED[2],
0
85
                            std::stoi(v[3]),
0
86
                            std::stoi(v[4])
0
87
                            );
0
88
            }
4
89
            else{
4
90
                return "need more parameter from-to-R-G-B";
4
91
            }
8
92
        }
0
93
        else {
0
94
            LED_Strip strip(v[2],v[3],v[4],v[5],v[6]);
0
95
            return my_data->main_iDomTools->ledOn(strip);
0
96
        }
8
97
    }
56
98
    else if (v[1]=="say"){
4
99
        if (v.size() > 3){
4
100
            std::vector<std::string> vTTS ={ my_data->main_iDomTools->getTextToSpeach()};
4
101
            my_data->main_iDomTools->textToSpeach(&vTTS);
4
102
            return "sad";
4
103
        }
4
104
    }
52
105
    else if (v[1]=="smog"){
4
106
        return my_data->main_iDomTools->getSmog()+" mg/m^3";
4
107
    }
48
108
    else if (v[1]=="230V"){
12
109
        if (v.size() > 2 && v[2]=="ON"){
4
110
            my_data->main_iDomTools->turnOnPrinter();
4
111
            return "230V ON";
4
112
        }
8
113
        else if(v.size() > 2 && v[2]=="OFF"){
4
114
            my_data->main_iDomTools->turnOffPrinter();
4
115
            return "230V OFF";
4
116
        }
4
117
        else {
4
118
            return "wrong paramiter";
4
119
        }
12
120
    }
36
121
    else if (v[1]=="wifi"){
4
122
        std::string readBuffer = useful_F_libs::httpPost("http://cyniu88.no-ip.pl/cgi-bin/kto_wifi.sh",10);
4
123
        return readBuffer;
4
124
    }
32
125
    else if (v[1]=="lightning"){
4
126
        std::stringstream readBuffer;
4
127
        readBuffer << my_data->main_iDomTools->getLightningStruct().data.str();
4
128
        readBuffer << std::endl;
4
129
        readBuffer << "bool: " << my_data->main_iDomTools->getLightningStruct().riseAlarm;
4
130
        readBuffer <<std::endl <<" time: ";
4
131
        readBuffer << Clock::getTime().getString();
4
132
        return readBuffer.str();
4
133
    }
28
134
    else if (v[1]=="kill"){
0
135
0
136
        if (v[2]=="thread"){
0
137
            my_data->main_THREAD_arr->at(std::stoi(v[3]) ).thread.~thread();
0
138
            return "done!";
0
139
        }
0
140
    }
28
141
    else if (v[1]=="facebook"){
0
142
        std::string msg;
0
143
        for (unsigned int i = 2; i < v.size(); ++i){
0
144
            msg+=" ";
0
145
            msg+=v[i];
0
146
        }
0
147
        return my_data->main_iDomTools->postOnFacebook(msg);
0
148
    }
28
149
    else if (v[1]=="viber"){
0
150
        std::string msg;
0
151
        for (unsigned int i = 2; i < v.size(); ++i){
0
152
            msg+=" ";
0
153
            msg+=v[i];
0
154
        }
0
155
        STATE stMSG = my_data->main_iDomTools->sendViberMsgBool(msg, my_data->server_settings->viberReceiver.at(0),
0
156
                                                     my_data->server_settings->viberSender);
0
157
        if(stMSG == STATE::SEND_OK){
0
158
            return "wiadomosc wyslana poprawnie";
0
159
        }
0
160
        else{
0
161
            return "blad wysylania wiadomosci - sprawdz logi";
0
162
        }
0
163
    }
28
164
    else if (v[1] == "camera"){
12
165
12
166
        if (v.size() < 4){
4
167
            return "not enough parameters";
4
168
        }
8
169
        if (v[2]=="LED" && v[3] == "ON"){
4
170
            my_data->main_iDomTools->cameraLedON(my_data->server_settings->cameraLedON);
4
171
        }
4
172
        else if (v[2]=="LED" && v[3] == "OFF"){
4
173
            my_data->main_iDomTools->cameraLedOFF(my_data->server_settings->cameraLedOFF);
4
174
        }
8
175
        return "led DONE";
12
176
    }
16
177
    else if (v[1]=="weather"){
0
178
0
179
        if (v.size() < 4){
0
180
            return "not enough parameters";
0
181
        }
0
182
        std::string tempHTML = my_data->main_iDomTools->getWeatherEvent(v[2],std::stoi(v[3]));
0
183
        return useful_F_libs::removeHtmlTag(tempHTML);
0
184
    }
16
185
    else if (v[1] == "KODI"){
12
186
        return my_data->main_iDomTools->startKodi_Thread();
12
187
    }
4
188
    else if (v[1]=="alarm"){
0
189
0
190
        if (v.size() < 3){
0
191
            return "not enough parameters";
0
192
        }
0
193
        if (v[2] == "OFF"){
0
194
            my_data->alarmTime.state = STATE::DEACTIVE;
0
195
            my_data->main_iDomStatus->setObjectState("alarm", my_data->alarmTime.state);
0
196
            my_data->main_iDomTools->saveState_iDom();
0
197
            return "alarm clock has been deactivated";
0
198
        }
0
199
        else if (v[2] == "GET"){
0
200
            return my_data->alarmTime.time.getString();
0
201
        }
0
202
        else if (v[2] == "SET" && v.size() == 5){
0
203
            if (v[3] == "from")
0
204
            {
0
205
                my_data->alarmTime.fromVolume = std::stoi(v[4]);
0
206
            }
0
207
            else if (v[3] == "to")
0
208
            {
0
209
                my_data->alarmTime.toVolume = std::stoi(v[4]);
0
210
            }
0
211
            else if (v[3] == "radio")
0
212
            {
0
213
                my_data->alarmTime.radioID = std::stoi(v[4]);
0
214
            }
0
215
            std::stringstream ret;
0
216
            ret << "The values has beedn set:" << std::endl;
0
217
            ret << "From Value: " << my_data->alarmTime.fromVolume << std::endl;
0
218
            ret << "To Value: " << my_data->alarmTime.toVolume << std::endl;
0
219
            ret << "Radio ID: " << my_data->alarmTime.radioID << std::endl;
0
220
            my_data->main_iDomTools->saveState_iDom();
0
221
            return ret.str();
0
222
        }
0
223
        else if (v[2] == "ON" && v.size() > 3){
0
224
            my_data->alarmTime.time = Clock(v[3]);
0
225
            my_data->alarmTime.state = STATE::ACTIVE;
0
226
            my_data->main_iDomStatus->setObjectState("alarm", my_data->alarmTime.state);
0
227
            my_data->main_iDomTools->saveState_iDom();
0
228
            return "alarm clock has been activated";
0
229
        }
0
230
    }
4
231
    return "iDom - unknown parameter: "+ v[1];
116
232
}
233
234
std::string command_iDom::help()
12
235
{
12
236
    std::stringstream help;
12
237
    help << "iDom - for control smart home" << std::endl;
12
238
    help << "iDom speakers ON/OFF - to on or off speakers" << std::endl;
12
239
    help << "iDom 230v ON/OFF     - to on or off printers" << std::endl;
12
240
    help << "iDom sunset/sunrise/day lenght - to show those parameters" << std::endl;
12
241
    help << "iDom sun        - get sunrise, sunset and day lenght" << std::endl;
12
242
    help << "iDom sysinfo    - get system info" << std::endl;
12
243
    help << "iDom text       - get text to speach" << std::endl;
12
244
    help << "iDom say <text> - say standatrd info or <text>" << std::endl;
12
245
    help << "iDom sms <text> - send sms<text>" << std::endl;
12
246
    help << "iDom LED <FROM> <TO> <R> <G> <B> - set RGB LED strip" << std::endl;
12
247
    help << "iDom LED OFF    - led off" << std::endl;
12
248
    help << "iDom LED set <from> <to> - set green led from to" << std::endl;
12
249
    help << "iDom temperature - get temperature from all termomether" << std::endl;
12
250
    help << "iDom temperature stats <name> - get temperature stats from termomether <name>" << std::endl;
12
251
    help << "iDom smog       - get current SMOG level (KRAKOW)" << std::endl;
12
252
    help << "iDom kill thread <ID>  - kill thread but denger!" << std::endl;
12
253
    help << "iDom camera LED ON/OFF - LED camera work" << std::endl;
12
254
    help << "iDom facebook ... - post on facebook wall" << std::endl;
12
255
    help << "iDom viber ...   - send viber msg" << std::endl;
12
256
    help << "iDom weather <city> <radius> - get weather alert" << std::endl;
12
257
    help << "iDom lightning  - get lightning alert" << std::endl;
12
258
    help << "iDom alarm ON/OFF hh:mm - set larm clock" << std::endl;
12
259
    help << "iDom alarm SET from/to/radio <value> - set larm clock" << std::endl;
12
260
    help << "iDom alarm GET - get alarm time" << std::endl;
12
261
    help << "iDom lock   - lock home" << std::endl;
12
262
    help << "iDom unlock - unlock home" << std::endl;
12
263
    help << "iDom KODI - start KODI smart TV" << std::endl;
12
264
    help << "iDom wifi - show all wifi client" << std::endl;
12
265
    return help.str();
12
266
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_ip.cpp
1
#include "command_ip.h"
2
3
command_ip::command_ip(const std::string &name):command(name)
24
4
{
24
5
}
6
7
std::string command_ip::execute(std::vector<std::string> &v, thread_data *my_data)
4
8
{
4
9
    return "iDom server IP: " +my_data->server_settings->SERVER_IP;
4
10
}
11
12
std::string command_ip::help()
4
13
{
4
14
    return "ip - show server IP address\n";
4
15
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_log.cpp
1
#include "command_log.h"
2
3
command_log::command_log(const std::string &name):command(name)
20
4
{
20
5
}
6
7
std::string command_log::execute(std::vector<std::string> &v, thread_data *my_data)
0
8
{
0
9
    std::string msg;
0
10
    for (unsigned int i = 2; i < v.size(); ++i)
0
11
    {
0
12
        msg+=" ";
0
13
        msg+=v[i];
0
14
    }
0
15
    log_file_mutex.mutex_lock();
0
16
    log_file_cout <<"USER:- " << logLevel(v[1]) << msg <<std::endl;;
0
17
    log_file_mutex.mutex_unlock();
0
18
    return "DONE!";
0
19
}
20
21
std::string command_log::help()
4
22
{
4
23
    std::stringstream help;
4
24
    help << "log <logLevel> \"***TXT***\"- add *** to iDom logfile" << std::endl;
4
25
    return help.str();
4
26
}
27
28
logger_level command_log::logLevel(const std::string &level)
0
29
{
0
30
    if (level == "VERBOSE"){
0
31
        return VERBOSE;
0
32
    }
0
33
    else if (level == "DEBUG"){
0
34
        return DEBUG;
0
35
    }
0
36
    else if (level == "INFO"){
0
37
        return INFO;
0
38
    }
0
39
    else if (level == "WARNING"){
0
40
        return WARNING;
0
41
    }
0
42
    else if (level == "ERROR"){
0
43
        return ERROR;
0
44
    }
0
45
    else if (level == "FATAL"){
0
46
        return FATAL;
0
47
    }
0
48
    else if (level == "CRITICAL"){
0
49
        return CRITICAL;
0
50
    }
0
51
puts ("nie mam co wysetlic wale verbose");
0
52
        return VERBOSE;
0
53
0
54
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_mpd.cpp
1
#include "command_mpd.h"
2
#include "../../blockQueue/blockqueue.h"
3
4
command_mpd::command_mpd(const std::string &name) :command(name)
20
5
{
20
6
}
7
8
std::string command_mpd::execute(std::vector<std::string> &v, thread_data *my_data)
0
9
{
0
10
    std::string str_buf;
0
11
0
12
    if (v[1]=="start")
0
13
    {
0
14
        if (v.size()>2)
0
15
        {
0
16
            if (std::stoi(v[2] ) > 0)
0
17
            {
0
18
                iDomTOOLS::MPD_play(my_data,std::stoi(v[2]));
0
19
                sleep(1);
0
20
                str_buf=my_data->ptr_MPD_info->songList[std::stoi(v[2])-1];
0
21
            }
0
22
        }
0
23
        else
0
24
        {
0
25
            iDomTOOLS::MPD_play(my_data);
0
26
            sleep(1);
0
27
            str_buf=my_data->ptr_MPD_info->title;
0
28
        }
0
29
        my_data->main_iDomTools->saveState_iDom();
0
30
    }
0
31
    else if (v[1]=="stop")
0
32
    {
0
33
        iDomTOOLS::MPD_stop();
0
34
        str_buf="stoped!";
0
35
        my_data->main_iDomTools->saveState_iDom();
0
36
    }
0
37
    else if (v[1]=="next")
0
38
    {
0
39
        iDomTOOLS::MPD_next();
0
40
        sleep(1);
0
41
        str_buf = my_data->ptr_MPD_info->radio + " : "+ my_data->ptr_MPD_info->title;
0
42
    }
0
43
    else if (v[1]=="prev")
0
44
    {
0
45
        iDomTOOLS::MPD_prev();
0
46
        sleep(1);
0
47
        str_buf=my_data->ptr_MPD_info->radio+ " : "+ my_data->ptr_MPD_info->title;
0
48
    }
0
49
    else if (v[1]=="pause")
0
50
    {
0
51
        iDomTOOLS::MPD_pause();
0
52
        str_buf="paused!";
0
53
    }
0
54
    else if (v[1]=="volume")
0
55
    {
0
56
        if (v[2]=="up")
0
57
        {
0
58
            iDomTOOLS::MPD_volumeUp();
0
59
        }
0
60
        else if (v[2]=="down")
0
61
        {
0
62
            iDomTOOLS::MPD_volumeDown();
0
63
        }
0
64
        else
0
65
        {
0
66
            int vol = std::stoi(v[2]);
0
67
            if (vol >0 && vol <100)
0
68
            {
0
69
                iDomTOOLS::MPD_volumeSet(my_data,vol);
0
70
            }
0
71
        }
0
72
        sleep(1);
0
73
        str_buf=std::to_string(my_data->ptr_MPD_info->volume);
0
74
    }
0
75
    else if (v[1]=="get")
0
76
    {
0
77
        if(v[2]=="volume")
0
78
        {
0
79
            str_buf=std::to_string(my_data->ptr_MPD_info->volume);
0
80
        }
0
81
        else if (v[2]=="info")
0
82
        {
0
83
            str_buf = my_data->ptr_MPD_info->radio + " : "+ my_data->ptr_MPD_info->title;
0
84
        }
0
85
    }
0
86
    else if (v[1]=="list")
0
87
    {
0
88
        for (auto i : my_data->ptr_MPD_info->songList)
0
89
            str_buf += i+"\n";
0
90
    }
0
91
    else
0
92
    {
0
93
        str_buf = "unknown parameter " + v[1];
0
94
    }
0
95
    return str_buf;
0
96
}
97
98
std::string command_mpd::help()
4
99
{
4
100
    std::stringstream help;
4
101
    help << "MPD - for control music player:" << std::endl;
4
102
    help << "parameter:" << std::endl;
4
103
    help << "\tstart - play music" << std::endl;
4
104
    help << "\tstop  - stop music" << std::endl;
4
105
    help << "\tpause - pause music" << std::endl;
4
106
    help << "\tnext  - next song" << std::endl;
4
107
    help << "\tprev  - previous song" << std::endl;
4
108
    help << "\tlist  - show playlist" << std::endl;
4
109
    help << "\tget volume - get volume %" << std::endl;
4
110
    help << "\tget info - get info about current song" << std::endl;
4
111
    help << "\tvolume up/down - increase/decrease volume 1%" << std::endl;
4
112
    return help.str();
4
113
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_ok.cpp
1
#include "command_ok.h"
2
3
command_ok::command_ok(const std::string &name):command(name)
24
4
{
24
5
}
6
7
std::string command_ok::execute(std::vector<std::string> &v, thread_data *my_data)
4
8
{
4
9
    return "\nEND\n";
4
10
}
11
12
std::string command_ok::help()
8
13
{
8
14
    return "ok - confirmation msg server response: END \n";
8
15
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_program.cpp
1
#include "command_program.h"
2
#include "../../functions/functions.h"
3
#include "../../433MHz/RFLink/rflinkhandler.h"
4
5
command_program::command_program(const std::string &name):command(name)
20
6
{
20
7
}
8
9
std::string command_program::execute(std::vector<std::string> &v, thread_data *my_data)
4
10
{
4
11
    std::string ret = help();
4
12
    if (v.size() <2 )
0
13
    {
0
14
        return "what?\n" + help();;
0
15
    }
4
16
    if (v[1] == "stop")
4
17
    {
4
18
        std::string s ="close server";
4
19
        useful_F::send_to_arduino_clock(my_data, "STOP");
4
20
        iDomTOOLS::MPD_stop();
4
21
        my_data->iDomProgramState = iDomStateEnum::CLOSE;
4
22
        my_data->main_iDomTools->saveState_iDom();
4
23
        throw s;
4
24
    }
0
25
    if (v.size() < 3 )
0
26
    {
0
27
        return "add more paramiters";
0
28
    }
0
29
    if(v[1] == "reload" && v[2] == "soft"){
0
30
        std::string s ="close server";
0
31
        useful_F::send_to_arduino_clock(my_data, "RELO");
0
32
        iDomTOOLS::MPD_stop();
0
33
        my_data->iDomProgramState = iDomStateEnum::RELOAD;
0
34
        my_data->main_iDomTools->saveState_iDom();
0
35
        throw s;
0
36
    }
0
37
    else if(v[1] == "reload" && v[2] == "hard")
0
38
    {
0
39
        std::string s ="close server";
0
40
        useful_F::send_to_arduino_clock(my_data, "UPAD");
0
41
        iDomTOOLS::MPD_stop();
0
42
        my_data->iDomProgramState = iDomStateEnum::HARD_RELOAD;
0
43
        my_data->main_iDomTools->saveState_iDom();
0
44
        throw s;
0
45
    }
0
46
    else if(v[1] == "clear" && v[2] == "ram")
0
47
    {
0
48
        system("sync; echo 3 > /proc/sys/vm/drop_caches");
0
49
        ret = "ram has beed freed";
0
50
    }
0
51
    else if(v[1] == "debuge" && v[2] == "variable")
0
52
    {
0
53
        std::stringstream r;
0
54
        r << "my_data->alarmTime.fromVolume \t" << my_data->alarmTime.fromVolume <<std::endl;
0
55
        r << "my_data->alarmTime.radioID \t" << my_data->alarmTime.radioID <<std::endl;
0
56
        r << "my_data->alarmTime.state \t" << stateToString( my_data->alarmTime.state) <<std::endl;
0
57
        r << "my_data->alarmTime.time \t" << my_data->alarmTime.time.getString() <<std::endl;
0
58
        r << "my_data->alarmTime.toVolume \t" << my_data->alarmTime.toVolume <<std::endl;
0
59
        r << std::endl;
0
60
        r << "my_data->encriptionKey \t" << my_data->encriptionKey <<std::endl;
0
61
        r << std::endl;
0
62
        r << "my_data->server_settings->BaudRate \t" << my_data->server_settings->BaudRate <<std::endl;
0
63
        r << "my_data->server_settings->cameraLedOFF \t" << my_data->server_settings->cameraLedOFF <<std::endl;
0
64
        r << "my_data->server_settings->cameraLedON \t" << my_data->server_settings->cameraLedON <<std::endl;
0
65
        r << "my_data->server_settings->cameraURL \t" << my_data->server_settings->cameraURL <<std::endl;
0
66
        r << "my_data->server_settings->encrypted \t" << my_data->server_settings->encrypted <<std::endl;
0
67
        r << "my_data->server_settings->facebookAccessToken \t" << my_data->server_settings->facebookAccessToken <<std::endl;
0
68
        r << "my_data->server_settings->ftpServer.URL \t" << my_data->server_settings->ftpServer.URL <<std::endl;
0
69
        r << "my_data->server_settings->ftpServer.user \t" << my_data->server_settings->ftpServer.user <<std::endl;
0
70
        r << "my_data->server_settings->ID_server \t" << my_data->server_settings->ID_server <<std::endl;
0
71
        r << "my_data->server_settings->lightningApiURL \t" << my_data->server_settings->lightningApiURL <<std::endl;
0
72
        r << "my_data->server_settings->MENU_PATH \t" << my_data->server_settings->MENU_PATH<<std::endl;
0
73
        r << "my_data->server_settings->MOVIES_DB_PATH \t" << my_data->server_settings->MOVIES_DB_PATH<<std::endl;
0
74
        r << "my_data->server_settings->MPD_IP \t" << my_data->server_settings->MPD_IP<<std::endl;
0
75
        r << "my_data->server_settings->omxplayerFile \t" << my_data->server_settings->omxplayerFile<<std::endl;
0
76
        r << "my_data->server_settings->PORT \t" << my_data->server_settings->PORT<<std::endl;
0
77
        r << "my_data->server_settings->portRS232 \t" << my_data->server_settings->portRS232<<std::endl;
0
78
        r << "my_data->server_settings->portRS232_clock \t" << my_data->server_settings->portRS232_clock<<std::endl;
0
79
        r << "my_data->server_settings->radio433MHzConfigFile \t" << my_data->server_settings->radio433MHzConfigFile<<std::endl;
0
80
        r << "my_data->server_settings->RFLinkBaudRate \t" << my_data->server_settings->RFLinkBaudRate<<std::endl;
0
81
        r << "my_data->server_settings->RFLinkPort \t" << my_data->server_settings->RFLinkPort<<std::endl;
0
82
        r << "my_data->server_settings->saveFilePath \t" << my_data->server_settings->saveFilePath<<std::endl;
0
83
        r << "my_data->server_settings->SERVER_IP \t" << my_data->server_settings->SERVER_IP<<std::endl;
0
84
        r << "my_data->server_settings->THREAD_CRON \t" << my_data->server_settings->THREAD_CRON<<std::endl;
0
85
        r << "my_data->server_settings->THREAD_DUMMY \t" << my_data->server_settings->THREAD_DUMMY<<std::endl;
0
86
        r << "my_data->server_settings->THREAD_IRDA \t" << my_data->server_settings->THREAD_IRDA<<std::endl;
0
87
        r << "my_data->server_settings->THREAD_MPD \t" << my_data->server_settings->THREAD_MPD<<std::endl;
0
88
        r << "my_data->server_settings->THREAD_RS232 \t" << my_data->server_settings->THREAD_RS232<<std::endl;
0
89
        r << "my_data->server_settings->TS_KEY \t" << my_data->server_settings->TS_KEY<<std::endl;
0
90
        r << "my_data->server_settings->viberAvatar \t" << my_data->server_settings->viberAvatar<<std::endl;
0
91
        r << "my_data->server_settings->viberReceiver.at(0) \t" << my_data->server_settings->viberReceiver.at(0)<<std::endl;
0
92
        r << "my_data->server_settings->viberSender \t" << my_data->server_settings->viberSender<<std::endl;
0
93
        r << "my_data->server_settings->viberToken \t" << my_data->server_settings->viberToken<<std::endl;
0
94
        r << "my_data->server_settings->v_delay \t" << my_data->server_settings->v_delay<<std::endl;
0
95
        r << std::endl;
0
96
        r << "my_data->server_settings->sleeper \t" << my_data->sleeper<<std::endl;
0
97
        r << std::endl;
0
98
        r << "my_data->iDomProgramState \t" << static_cast<int>(my_data->iDomProgramState)<<std::endl;
0
99
        r << std::endl;
0
100
        r << "my_data->main_iDomStatus \t" << my_data->main_iDomStatus->getAllObjectsStateString()<<std::endl;
0
101
        r << std::endl;
0
102
        r << "my_data->idom_all_state.houseState \t" <<stateToString(my_data->idom_all_state.houseState)<<std::endl;
0
103
        r << std::endl;
0
104
        r << "my_data->now_time \t" << my_data->now_time<<std::endl;
0
105
        r << "my_data->start - time \t" << my_data->start<<std::endl;
0
106
        r << std::endl;
0
107
        r << "my_data->pointer.ptr_buf \t" << my_data->pointer.ptr_buf<<std::endl;
0
108
        r << "my_data->pointer.ptr_who \t" << my_data->pointer.ptr_who<<std::endl;
0
109
0
110
        r << std::endl;
0
111
        r << "my_data->ptr_MPD_info->artist \t" << my_data->ptr_MPD_info->artist<<std::endl;
0
112
        r << "my_data->ptr_MPD_info->currentSongID \t" << my_data->ptr_MPD_info->currentSongID<<std::endl;
0
113
        r << "my_data->ptr_MPD_info->isPlay \t" << my_data->ptr_MPD_info->isPlay<<std::endl;
0
114
        r << "my_data->ptr_MPD_info->radio \t" << my_data->ptr_MPD_info->radio<<std::endl;
0
115
        r << "my_data->ptr_MPD_info->songList.at(0) \t" << my_data->ptr_MPD_info->songList.at(0)<<std::endl;
0
116
        r << "my_data->ptr_MPD_info->title \t" << my_data->ptr_MPD_info->title<<std::endl;
0
117
        r << "my_data->ptr_MPD_info->volume \t" << my_data->ptr_MPD_info->volume<<std::endl;
0
118
0
119
        r << std::endl;
0
120
        r << "my_data->main_RFLink->okTime \t" << my_data->main_RFLink->okTime<<std::endl;
0
121
        r << "my_data->main_RFLink->pingTime \t" << my_data->main_RFLink->pingTime<<std::endl;
0
122
0
123
        r << std::endl;
0
124
        r << "my_data->mainLCD-> \t" << my_data->mainLCD->getData() <<std::endl;
0
125
0
126
        r << "END.";
0
127
        ret = r.str();
0
128
    }
0
129
    else if(v[1] == "raspberry")
0
130
    {
0
131
        system(v[2].c_str());
0
132
        ret = "ram has beed freed";
0
133
    }
0
134
    else
0
135
    {
0
136
        ret = " what? - "+ v[1];
0
137
    }
0
138
    return ret;
0
139
}
140
141
std::string command_program::help()
8
142
{
8
143
    std::stringstream help;
8
144
    help << "program stop - close iDom server"<< std::endl;
8
145
    help << "program reload soft - reload iDom server" << std::endl;
8
146
    help << "program reload hard - reload iDom server" << std::endl;
8
147
    help << "program clear ram   - reload iDom server" << std::endl;
8
148
    help << "program debuge variable - show value iDom server variable" << std::endl;
8
149
    help << "program raspberry <command> - put command to raspberry " << std::endl;
8
150
    return help.str();
8
151
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_put.cpp
1
#include "command_put.h"
2
#include "../../src/CRON/cron.hpp"
3
4
command_put::command_put(const std::string &name):command(name)
20
5
{
20
6
}
7
8
std::string command_put::execute(std::vector<std::string> &v, thread_data *my_data)
0
9
{
0
10
    std::string str_buf = "command put - wrong paramiter: ";
0
11
    if (v.size() > 1){
0
12
        if (v[1] =="temperature")
0
13
        {
0
14
            str_buf.erase();
0
15
            my_data->main_iDomTools->send_temperature_thingSpeak();
0
16
            str_buf = "DONE";
0
17
        }
0
18
    }
0
19
    return str_buf;
0
20
}
21
22
std::string command_put::help()
4
23
{
4
24
    std::stringstream help;
4
25
    help << "put <parameter> - " << std::endl << std::endl;
4
26
    help << "parameter:" << std::endl;
4
27
    help << "\ttemperature - put actual temperature from inside and outside and smog on thingspeak\n" << std::endl;
4
28
    return help.str();
4
29
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_show.cpp
1
#include <strstream>
2
#include "command_show.h"
3
#include "../../src/functions/functions.h"
4
5
command_show::command_show(const std::string &name):command(name)
20
6
{
20
7
20
8
}
9
10
std::string command_show::execute(std::vector<std::string> &v, thread_data *my_data)
0
11
{
0
12
    std::string str_buf = "show what? ";
0
13
    if (v.size() > 1){
0
14
        if (v[1] =="log")
0
15
        {
0
16
            if (v.size() >2 && v.size() < 4){
0
17
                 return useful_F::l_send_file(_logfile,v[2],true);
0
18
            }
0
19
            else if (v.size() > 3){
0
20
                if (v[2] == "no"){
0
21
                 return useful_F::l_send_file(_logfile,v[3],false);
0
22
                }
0
23
                else{
0
24
                    return "do you mean : show log no <string>? ";
0
25
                }
0
26
            }
0
27
0
28
            return useful_F::l_send_file(_logfile,"");
0
29
0
30
        }
0
31
        if (v[1]=="thread")
0
32
        {
0
33
            if (v.size() < 3){
0
34
                return " No ID";
0
35
            }
0
36
            else {
0
37
                if (v [2] !="all"){
0
38
                    std::stringstream ss;
0
39
                    ss << my_data->main_THREAD_arr->at(std::stoi(v[2])).thread_ID;
0
40
                    str_buf = my_data->main_THREAD_arr->at(std::stoi(v[2])).thread_name;
0
41
                    str_buf += "ID: ";
0
42
                    str_buf += ss.str();
0
43
                    str_buf += " socket: ";
0
44
                    str_buf += std::to_string(my_data->main_THREAD_arr->at(std::stoi(v[2])).thread_socket);
0
45
                    return str_buf;
0
46
                }
0
47
                else{
0
48
                    str_buf.erase();
0
49
                    std::stringstream ss;
0
50
                    for (int i =0; i< iDomConst::MAX_CONNECTION;++i)
0
51
                    {
0
52
                        ss.clear();
0
53
                        ss = std::stringstream();
0
54
                        str_buf += std::to_string(i)+" ";
0
55
                        str_buf += my_data->main_THREAD_arr->at(i).thread_name;
0
56
                        str_buf += "\t ID: ";
0
57
                        ss << my_data->main_THREAD_arr->at(i).thread_ID;
0
58
                        str_buf += ss.str();
0
59
                        int idSocket = my_data->main_THREAD_arr->at(i).thread_socket;
0
60
0
61
                        if (idSocket != 0 && idSocket != 1){
0
62
                            str_buf += " socket: ";
0
63
                            str_buf += std::to_string(my_data->main_THREAD_arr->at(i).thread_socket);
0
64
                        }
0
65
                        str_buf += "\n";
0
66
                    }
0
67
                    return str_buf;
0
68
                }
0
69
            }
0
70
        }
0
71
        else {
0
72
            return "wrong parameter: "+v[1];
0
73
        }
0
74
    }
0
75
    return str_buf;
0
76
}
77
78
std::string command_show::help()
4
79
{
4
80
    std::stringstream help;
4
81
    help << "show <parameter>- for show something" <<std::endl << std::endl;
4
82
    help << "parameter:" << std::endl;
4
83
    help << "\tlog             - show all server log" << std::endl;
4
84
    help << "\tlog <string>    - show all server log lines which contain <string>" << std::endl;
4
85
    help << "\tlog no <string> - show all server log lines which NO contain <string>" << std::endl;
4
86
    help << "\tthread all      - show all server thread pid " << std::endl;
4
87
    help << "\tthread <number> - show server <number> thread pid " << std::endl;
4
88
4
89
    return help.str();
4
90
}
91
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_sleep.cpp
1
#include "command_sleep.h"
2
#include "../../functions/functions.h"
3
#include "../../thread_functions/iDom_thread.h"
4
5
command_sleep::command_sleep(const std::string &name):command(name)
20
6
{
20
7
}
8
9
std::string command_sleep::execute(std::vector<std::string> &v, thread_data *my_data)
0
10
{   if (v.size()== 1)
0
11
    {
0
12
        return "sleep set to: "+ std::to_string(my_data->sleeper);
0
13
    }
0
14
    else if (v.size() == 3 ){
0
15
        if (v[1] == "set"){
0
16
            int sleep = 0;
0
17
            try {
0
18
                sleep = std::stoi(v[2]);
0
19
            }
0
20
            catch (...){
0
21
                return "system need intiger > 0 not: " +v[2];
0
22
            }
0
23
0
24
            my_data->sleeper = sleep;
0
25
0
26
            return iDOM_THREAD::start_thread("Sleep MPD",useful_F::sleeper_mpd,my_data);
0
27
        }
0
28
        else {
0
29
            return "wrong parametr "+v[1];
0
30
        }
0
31
    }
0
32
    return "internal error";
0
33
}
34
35
std::string command_sleep::help()
4
36
{
4
37
    std::stringstream help;
4
38
    help << "sleep - show actual time to stop play music" << std::endl;
4
39
    help << "sleep set <int> - start sleep for <int> minutes" << std::endl;
4
40
4
41
    return help.str();
4
42
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_state.cpp
1
#include "command_state.h"
2
3
command_state::command_state(const std::string &name):command(name)
20
4
{
20
5
}
6
7
std::string command_state::execute(std::vector<std::string> &v, thread_data *my_data)
0
8
{
0
9
    std::string ret = "need parameter!\n" + help();
0
10
    if (v.size()<2)
0
11
    {
0
12
0
13
    }
0
14
    if (v[1] == "all")
0
15
    {
0
16
        return my_data->main_iDomStatus->getAllObjectsStateString();
0
17
    }
0
18
    if (v[1] != "all")
0
19
    {
0
20
        return my_data->main_iDomStatus->getObjectStateString(v[1]);
0
21
    }
0
22
    return ret;
0
23
}
24
25
std::string command_state::help()
4
26
{
4
27
    std::stringstream help;
4
28
    help << "state all/<name> - show state" << std::endl;
4
29
    return help.str();
4
30
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/command_uptime.cpp
1
#include "command_uptime.h"
2
#include "../../src/functions/functions.h"
3
4
command_UPTIME::command_UPTIME(const std::string &name):command(name)
20
5
{
20
6
20
7
}
8
9
std::string command_UPTIME::execute(std::vector<std::string> &v, thread_data *my_data)
0
10
{
0
11
    std::string str_buf;
0
12
    time(&my_data->now_time);
0
13
    str_buf ="uptime: ";
0
14
    str_buf.append(useful_F::sek_to_uptime(difftime(my_data->now_time,my_data->start) ) );
0
15
    return str_buf;
0
16
}
17
18
std::string command_UPTIME::help()
4
19
{
4
20
    std::stringstream help;
4
21
    help << "uptime - show server uptime" << std::endl;
4
22
    return help.str();
4
23
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/commandexit.cpp
1
#include "commandexit.h"
2
3
commandEXIT::commandEXIT(const std::string &name):command(name)
20
4
{
20
5
}
6
7
std::string commandEXIT::execute(std::vector<std::string> &v, thread_data *my_data)
0
8
{
0
9
    return "\nEND.\n";
0
10
}
11
12
std::string commandEXIT::help()
4
13
{
4
14
    return "exit - disconnect from server\n";
4
15
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/commandrs232.cpp
1
#include "commandrs232.h"
2
#include "../../src/functions/functions.h"
3
4
commandRS232::commandRS232(const std::string &name):command(name)
20
5
{
20
6
}
7
std::string commandRS232::execute(std::vector<std::string> &v, thread_data *my_data)
0
8
{
0
9
    std::string str_buf ="default";
0
10
0
11
    if (v[1]=="get")
0
12
    {
0
13
        if (v[2]=="temperature")
0
14
        {
0
15
            str_buf = useful_F::send_to_arduino(my_data,"temperature:339;");
0
16
            str_buf += std::to_string(++counter);
0
17
        }
0
18
        else
0
19
        {
0
20
            str_buf = ("wrong parameter: "+v[2]);
0
21
        }
0
22
    }
0
23
0
24
    else if (v[1]=="send")
0
25
    {
0
26
        str_buf = useful_F::send_to_arduino(my_data,v[2]);
0
27
    }
0
28
    else if (v[1]=="error")
0
29
    {
0
30
        std::string msg;
0
31
        for (unsigned int i = 2; i < v.size(); ++i)
0
32
        {
0
33
            msg+=" ";
0
34
            msg+=v[i];
0
35
        }
0
36
        if(v[2]=="Temperature" && v[3]=="error")
0
37
        {
0
38
0
39
            my_data->myEventHandler.run("RS232")->addEvent("RS232 error event: "+msg);
0
40
            log_file_mutex.mutex_lock();
0
41
            log_file_cout << WARNING<< "RS232 ERROR event: " << msg << std::endl;
0
42
            log_file_mutex.mutex_unlock();
0
43
        }
0
44
        else if (v[2]=="test" && v[3]=="msg")
0
45
        {
0
46
            log_file_mutex.mutex_lock();
0
47
            log_file_cout << DEBUG << "RS232 ERROR debug : "<<msg << std::endl;
0
48
            log_file_mutex.mutex_unlock();
0
49
        }
0
50
        else
0
51
        {
0
52
            log_file_mutex.mutex_lock();
0
53
            log_file_cout << CRITICAL << "RS232 ERROR unknown : "<<msg << std::endl;
0
54
            log_file_mutex.mutex_unlock();
0
55
        }
0
56
    }
0
57
    else
0
58
    {
0
59
        str_buf = ("wrong parameter: "+v[1]);
0
60
    }
0
61
    return str_buf;
0
62
}
63
64
std::string commandRS232::help()
4
65
{
4
66
    std::stringstream help;
4
67
    help << "RS232 - communication with Arduino:" << std::endl;
4
68
    help << "parameter:" << std::endl << std::endl;
4
69
    help << "\tsend <command> - send <command> to Arduino" << std::endl;
4
70
    help << "\tget <param> - get <param> from Arduino" << std::endl;
4
71
    help << "\t\ttemperature - get temeprature INSIDE + OUTSIDE" << std::endl;
4
72
4
73
    return help.str();
4
74
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandClass/commandtest.cpp
1
#include "commandtest.h"
2
#include "../../functions/functions.h"
3
#include "../../../ftplibpp/ftplib.h"
4
5
commandTEST::commandTEST(const std::string &name):command(name)
20
6
{
20
7
}
8
9
std::string commandTEST::execute(std::vector<std::string> &v, thread_data *my_data)
0
10
{
0
11
0
12
    if (v[1] == "test")
0
13
    {
0
14
        std::string msg = "test - for test ";
0
15
        my_data->main_iDomTools->runOnSunrise();
0
16
        return msg;
0
17
    }
0
18
    else if (v[1] == "throw")
0
19
    {
0
20
        throw "test throw";
0
21
    }
0
22
    return help();
0
23
}
24
std::string commandTEST::help()
4
25
{
4
26
    std::stringstream help;
4
27
    help << "test - for test" << std::endl;
4
28
    help << "throw - trow test reload program" << std::endl;
4
29
    return help.str();
4
30
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandhandler.cpp
1
#include <iostream>
2
#include "../../libs/emoji/emoji.h"
3
#include "commandhandler.h"
4
#include "commandClass/command_mpd.h"
5
#include "commandClass/commandrs232.h"
6
#include "commandClass/command_uptime.h"
7
#include "commandClass/command_big.h"
8
#include "commandClass/command_clock.h"
9
#include "commandClass/command_hello.h"
10
#include "commandClass/command_help.h"
11
#include "commandClass/command_ip.h"
12
#include "commandClass/command_put.h"
13
#include "commandClass/command_sleep.h"
14
#include "commandClass/command_ok.h"
15
#include "commandClass/command_show.h"
16
#include "commandClass/command_idom.h"
17
#include "commandClass/command_program.h"
18
#include "commandClass/commandexit.h"
19
#include "commandClass/commandtest.h"
20
#include "commandClass/command_log.h"
21
#include "commandClass/command_state.h"
22
#include "commandClass/command_ardu.h"
23
24
commandHandler::commandHandler(thread_data * my_data)
20
25
{
20
26
    std::unique_ptr <command> test(new commandTEST("test") );
20
27
    commandMap.insert( std::make_pair(test->getCommandName(),std::move( test )) );
20
28
20
29
    std::unique_ptr <command> program(new command_program("program") );
20
30
    commandMap.insert( std::make_pair(program->getCommandName(),std::move( program )) );
20
31
20
32
    std::unique_ptr <command> eexit(new commandEXIT("exit"));
20
33
    commandMap.insert( std::make_pair(eexit->getCommandName(),std::move( eexit )) );
20
34
20
35
    std::unique_ptr <command> MPD(new command_mpd("MPD"));
20
36
    commandMap.insert(std::make_pair(MPD->getCommandName(), std::move (MPD)));
20
37
20
38
    std::unique_ptr <command> RS232 (new commandRS232("RS232"));
20
39
    commandMap.insert(std::make_pair(RS232->getCommandName(), std::move(RS232)));
20
40
20
41
    std::unique_ptr <command> uptime (new command_UPTIME("uptime"));
20
42
    commandMap.insert(std::make_pair(uptime->getCommandName(), std::move(uptime)));
20
43
20
44
    std::unique_ptr <command> big (new command_big("big"));
20
45
    commandMap.insert(std::make_pair(big->getCommandName(), std::move(big)));
20
46
20
47
    std::unique_ptr <command> clock (new command_clock("clock"));
20
48
    commandMap.insert(std::make_pair(clock->getCommandName(), std::move(clock)));
20
49
20
50
    std::unique_ptr <command> hello (new command_hello("hello"));
20
51
    commandMap.insert(std::make_pair(hello->getCommandName(), std::move(hello)));
20
52
20
53
    std::unique_ptr <command> help (new command_help("help"));
20
54
    commandMap.insert(std::make_pair(help->getCommandName(), std::move(help)));
20
55
20
56
    std::unique_ptr <command> ip (new command_ip("ip"));
20
57
    commandMap.insert(std::make_pair(ip->getCommandName(), std::move(ip)));
20
58
20
59
    std::unique_ptr <command> ok (new command_ok("ok"));
20
60
    commandMap.insert(std::make_pair(ok->getCommandName(), std::move(ok)));
20
61
20
62
    std::unique_ptr <command> show (new command_show("show"));
20
63
    commandMap.insert(std::make_pair(show->getCommandName(), std::move(show)));
20
64
20
65
    std::unique_ptr <command> sleep (new command_sleep("sleep"));
20
66
    commandMap.insert(std::make_pair(sleep->getCommandName(), std::move(sleep)));
20
67
20
68
    std::unique_ptr <command> put (new command_put("put"));
20
69
    commandMap.insert(std::make_pair(put->getCommandName(), std::move(put)));
20
70
20
71
    std::unique_ptr <command> iDom (new command_iDom("iDom"));
20
72
    commandMap.insert(std::make_pair(iDom->getCommandName(), std::move(iDom)));
20
73
20
74
    std::unique_ptr <command> log (new command_log("log"));
20
75
    commandMap.insert(std::make_pair(log->getCommandName(), std::move(log)));
20
76
20
77
    std::unique_ptr <command> state (new command_state("state"));
20
78
    commandMap.insert(std::make_pair(state->getCommandName(), std::move(state)));
20
79
20
80
    std::unique_ptr <command> ardu (new command_ardu("ardu", my_data));
20
81
    commandMap.insert(std::make_pair(ardu->getCommandName(), std::move(ardu)));
20
82
20
83
    this->my_data = my_data;
20
84
    this->my_data->commandMapPtr = &commandMap;
20
85
}
86
87
commandHandler::~commandHandler()
20
88
{
20
89
    puts("commandHandler::~commandHandler()");
20
90
}
91
92
std::string commandHandler::run(std::vector<std::string> &v, thread_data *my_data)
8
93
{
8
94
    if (commandMap.find(v[0]) == commandMap.end()){
4
95
        std::fstream log;
4
96
        log.open( "/mnt/ramdisk/command.txt", std::ios::binary | std::ios::in | std::ios::out|std::ios::app );
4
97
        log << v[0] << std::endl;
4
98
        log.close();
4
99
        return EMOJI::emoji(E_emoji::WARNING_SIGN)+" unknown command: "+ v[0];
4
100
    }
4
101
    else{
4
102
        return commandMap[v[0]]->execute(v,my_data);
4
103
    }
8
104
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandhandlerroot.cpp
1
#include "commandhandlerroot.h"
2
#include "commandClass/command_cmd.h"
3
#include "commandClass/command_event.h"
4
#include "commandClass/command_433mhz.h"
5
6
commandHandlerRoot::commandHandlerRoot(thread_data * my_data): commandHandler(my_data)
20
7
{
20
8
    std::unique_ptr <command> cmd (new command_cmd("cmd"));
20
9
    commandMap.insert(std::make_pair(cmd->getCommandName(), std::move(cmd)));
20
10
20
11
    std::unique_ptr <command> event (new command_event("event"));
20
12
    commandMap.insert(std::make_pair(event->getCommandName(), std::move(event)));
20
13
20
14
    std::unique_ptr <command> r_433MHz (new command_433MHz("433MHz"));
20
15
    commandMap.insert(std::make_pair(r_433MHz->getCommandName(), std::move(r_433MHz)));
20
16
}
17
18
commandHandlerRoot::~commandHandlerRoot()
20
19
{
20
20
    puts("commandHandlerRoot::~commandHandlerRoot()");
20
21
}
/home/pi/programowanie/iDom_server_OOP/src/command/commandhandlerrs232.cpp
1
#include "commandhandlerrs232.h"
2
#include "commandClass/command_cmd.h"
3
#include "commandClass/command_event.h"
4
5
6
commandHandlerRS232::commandHandlerRS232(thread_data *my_data):commandHandlerRoot(my_data)
0
7
{
0
8
0
9
}
10
11
commandHandlerRS232::~commandHandlerRS232()
0
12
{
0
13
    puts("commandHandlerRS232::~commandHandlerRS232()");
0
14
}
/home/pi/programowanie/iDom_server_OOP/src/command/test/commandhandler_stub.cpp
1
#include "../../src/functions/functions.h"
2
#include "../../src/LCD_c/lcd_c.h"
3
4
//std::string useful_F::send_to_arduino (thread_data *my_data_logic, const std::string& msg){
5
//    return "retunr test ";
6
//}
7
4
8
std::string useful_F::send_to_arduino_clock (thread_data *my_data_logic, std::string msg){
4
9
	return "retunr test ";
4
10
}
11
std::string useful_F::l_send_file(std::string path, std::string find, bool reverse )
0
12
{
0
13
	return "retunr test ";
0
14
}
15
0
16
std::string LCD_c::getData(){
0
17
    return " data test";
0
18
}
/home/pi/programowanie/iDom_server_OOP/src/files_tree/files_tree.cpp
1
#include "files_tree.h"
2
3
bool comper (const movie_database & a , const movie_database& b)
1.10k
4
{
1.10k
5
    return a.files_name < b.files_name;
1.10k
6
}
7
files_tree::files_tree (const std::string& path, LCD_c *mainLCD_PTR):database_path(path),w_serial( "([Ss]\\d{1,3}[Ee]\\d{1,3})")
8
48
9
{
48
10
    //database_path = path;
48
11
    mainLCD = mainLCD_PTR;
48
12
    //tree_stack.push(database_path);
48
13
    i_stack.push(0);
48
14
    i = 0;
48
15
    get_list(database_path);
48
16
}
17
bool files_tree::is_file() const
12
18
{
12
19
    return movie_database_vector[i].is_file;
12
20
}
21
22
void files_tree::next()
12
23
{   
12
24
    ++i;
12
25
    ////std::cout << " dodaje " << i << std::endl;
12
26
    if (get_vector_size() == i ){
4
27
        i=0;
4
28
    }
12
29
}
30
31
void files_tree::previous()
20
32
{
20
33
    --i;
20
34
    ////std::cout << " odejmuje " << i << std::endl;
20
35
20
36
    if ( i <0 )
8
37
    {
8
38
        i=get_vector_size()-1;
8
39
    }
20
40
}
41
42
int files_tree::get_vector_size () const
20
43
{
20
44
    return movie_database_vector.size();
20
45
}
46
void files_tree::vector_clear ()
56
47
{
56
48
    movie_database_vector.clear();
56
49
}
50
int files_tree::get_i()
4
51
{ if (i_stack.size() >1 ) {
4
52
        int i = i_stack.top();
4
53
        i_stack.pop();
4
54
        return i;
4
55
    }
4
56
    else
0
57
        return 0;
4
58
}
59
60
void files_tree::enter_dir()
4
61
{
4
62
    i_stack.push(i); // wpisuje na stos kolejna wersje licznika i
4
63
4
64
    if (movie_database_vector[i].is_file == false) {
4
65
        get_list (movie_database_vector[i].path);
4
66
        i=0;
4
67
    }
4
68
4
69
}
70
void files_tree::enter_dir(const std::string& path)
0
71
{	//tree_stack.push(path);
0
72
    get_list (path);
0
73
}
74
75
void files_tree::back_dir()
4
76
{
4
77
    if ( tree_stack.size() >1 ) {
4
78
        tree_stack.pop();
4
79
        std::string path = tree_stack.top();
4
80
        tree_stack.pop();
4
81
        i=get_i();
4
82
        get_list (path);
4
83
        return;
4
84
    }
0
85
    i=get_i();
0
86
0
87
    ////std::cout << " III ma teraz : " << i << std::endl;
0
88
    get_list (database_path);
0
89
    return;
4
90
}
91
92
std::string files_tree::show_list()
96
93
{
96
94
    //std::cout << "iteracja!!!!!!!!!!!!!!!!!!!!!!: " << i <<"rozmiar vectora : " << get_vector_size() << std::endl;
96
95
    if (movie_database_vector[i].is_file == true ) {
48
96
        //std::cout << "wypisuje sciezke pliku " << movie_database_vector[i].path <<" | " <<movie_database_vector[i].files_name.substr(0,16)<< std::endl;
48
97
48
98
        mainLCD->printString(true,0,0,movie_database_vector[i].files_name.substr(0,16));
48
99
        if( regex_search(movie_database_vector[i].path,result,w_serial) )
48
100
        {
48
101
            mainLCD->printString(false,10,1,movie_database_vector[i].files_name.substr( movie_database_vector[i].files_name.size()-4,movie_database_vector[i].files_name.size()));
48
102
            mainLCD->printString(false, 1,1,result[0]);
48
103
        }
48
104
        else
0
105
        {
0
106
            mainLCD->printString(false,10,1,movie_database_vector[i].files_name.substr( movie_database_vector[i].files_name.size()-4,movie_database_vector[i].files_name.size()));
0
107
        }
48
108
    }
48
109
    else {
48
110
        mainLCD->printString(true,0,0,movie_database_vector[i].files_name+"/");
48
111
    }
96
112
    return movie_database_vector[i].path;
96
113
}
114
56
115
void files_tree::get_list(std::string path) {
56
116
    tree_stack.push(path);
56
117
    vector_clear(); // czyscimy vector
56
118
    std::string path2 =path;
56
119
    std::string v_path ,tmp_string;
56
120
56
121
    if(sciezka = opendir( path.c_str() )) {
56
122
324
123
        while(( plik = readdir( sciezka ) ) )
268
124
        {
268
125
            path2 =path;
268
126
            if (static_cast<int>(plik->d_type) == 4 /*&& strcmp( plik->d_name, "..") && strcmp( plik->d_name, ".")*/)
164
127
            {
164
128
                temp.is_file=false;
164
129
            }
268
130
            else //if ( (int)plik->d_type == 8 && strcmp( plik->d_name, "..") && strcmp( plik->d_name, "."))
104
131
            {
104
132
                temp.is_file=true;
104
133
            }
268
134
268
135
            v_path= path2;
268
136
            v_path+="/";
268
137
            tmp_string.assign(plik->d_name);
268
138
            v_path+=tmp_string;
268
139
            temp.path =v_path;
268
140
            temp.files_name.assign(plik->d_name);
268
141
            movie_database_vector.push_back(temp);
268
142
        }// end while
56
143
        sort(movie_database_vector.begin(),movie_database_vector.end(), comper);
56
144
        closedir( sciezka );
56
145
    }
56
146
}
/home/pi/programowanie/iDom_server_OOP/src/functions/../thread_functions/../iDom_server_OOP.h
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
112
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
48
41
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    RADIO_EQ_CONTAINER *main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/home/pi/programowanie/iDom_server_OOP/src/functions/../thread_functions/../logger/logger.hpp
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
28
84
    {
28
85
        *static_cast<std::ostringstream *>(this) << t;
28
86
        return (*this);
28
87
    }
_ZN6LoggerlsIA44_cEERS_RKT_
0
84
    {
0
85
        *static_cast<std::ostringstream *>(this) << t;
0
86
        return (*this);
0
87
    }
_ZN6LoggerlsIA23_cEERS_RKT_
8
84
    {
8
85
        *static_cast<std::ostringstream *>(this) << t;
8
86
        return (*this);
8
87
    }
_ZN6LoggerlsIA14_cEERS_RKT_
20
84
    {
20
85
        *static_cast<std::ostringstream *>(this) << t;
20
86
        return (*this);
20
87
    }
_ZN6LoggerlsIA27_cEERS_RKT_
0
84
    {
0
85
        *static_cast<std::ostringstream *>(this) << t;
0
86
        return (*this);
0
87
    }
_ZN6LoggerlsIiEERS_RKT_
0
84
    {
0
85
        *static_cast<std::ostringstream *>(this) << t;
0
86
        return (*this);
0
87
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/home/pi/programowanie/iDom_server_OOP/src/functions/functions2.cpp
1
#include <iostream>
2
#include <fstream>
3
#include <regex>
4
#include <iterator>
5
#include <vector>
6
7
#include "functions.h"
8
#include "../thread_functions/iDom_thread.h"
9
88
10
std::vector<std::string> useful_F::split(const std::string& s, char separator ){
88
11
    std::vector<std::string> output;
88
12
    std::string::size_type prev_pos = 0, pos = 0;
88
13
204
14
    while((pos = s.find(separator, pos)) != std::string::npos)
116
15
    {
116
16
        std::string substring( s.substr(prev_pos, pos-prev_pos) );
116
17
        output.push_back(substring);
116
18
        prev_pos = ++pos;
116
19
    }
88
20
    try
88
21
    {
88
22
        output.push_back(s.substr(prev_pos, pos-prev_pos)); // Last word
88
23
    }
88
24
    catch (...)
0
25
    {
0
26
        log_file_mutex.mutex_lock();
0
27
        log_file_cout << CRITICAL << "wyjatek substr() w useful_F::split() !!!!!!"<< std::endl;
0
28
        log_file_mutex.mutex_unlock();
0
29
    }
88
30
    return output;
88
31
}
32
thread_data* useful_F::myStaticData = std::nullptr_t();
33
void useful_F::setStaticData(thread_data *my_dataPtr)
4
34
{
4
35
    myStaticData = my_dataPtr;
4
36
}
37
20
38
void useful_F::tokenizer ( std::vector <std::string> &command, std::string separator, std::string &text){
20
39
    std::string temp;
20
40
20
41
    for(char n: text)
176
42
    { // the initializer may be an array
176
43
        bool is_sep = false;
176
44
        for(char m: separator)
476
45
        {
476
46
            if (n == m)
20
47
                is_sep = true;
476
48
        }
176
49
        if (is_sep == false)
156
50
            temp += n;
176
51
        else
20
52
        {
20
53
            if (!temp.empty())
20
54
            {
20
55
                command.push_back( temp);
20
56
                temp = "";
20
57
            }
20
58
        }
176
59
    }
20
60
    if (!temp.empty())
12
61
        command.push_back(temp);
20
62
20
63
    if (command.size() == 0)
8
64
        throw std::string("command empty");
20
65
}
66
67
////// watek sleeper
68
void useful_F::sleeper_mpd (thread_data *my_data, const std::string& threadName)
8
69
{
8
70
    unsigned int t = 60/my_data->sleeper;
8
71
    unsigned int k = 0;
8
72
52
73
    for (; my_data->sleeper >0; my_data->sleeper-- )
44
74
    {
44
75
        useful_F::sleep_1min();
44
76
        k += t;
44
77
        my_data->main_iDomTools->ledClear(0,k);
44
78
    }
8
79
    my_data->main_iDomTools->ledOFF();
8
80
    my_data->main_iDomTools->MPD_stop();
8
81
    my_data->main_iDomTools->turnOff433MHzSwitch("listwa");
8
82
8
83
    log_file_mutex.mutex_lock();
8
84
    log_file_cout << INFO<< "zaczynam procedure konca watku " << threadName << std::endl;
8
85
    log_file_mutex.mutex_unlock();
8
86
8
87
    iDOM_THREAD::stop_thread(threadName,my_data);
8
88
8
89
    log_file_mutex.mutex_lock();
8
90
    log_file_cout << INFO<< "koniec watku SLEEP_MPD" << std::endl;
8
91
    log_file_mutex.mutex_unlock();
8
92
}
93
94
///////////////////////////////////////////////////////////////////////////////////////////////////// watek kodi
95
void useful_F::kodi (thread_data *my_data, const std::string& threadName)
8
96
{
8
97
    log_file_mutex.mutex_lock();
8
98
    log_file_cout << INFO<< "start wątku "<<threadName << std::endl;
8
99
    log_file_mutex.mutex_unlock();
8
100
8
101
    my_data->mainLCD->set_print_song_state(100);
8
102
    my_data->mainLCD->printString(false,2,1,"  KODI");
8
103
8
104
    my_data->main_iDomStatus->setObjectState("KODI",STATE::ACTIVE);
8
105
    //status mpd
8
106
    STATE musicState = my_data->main_iDomStatus->getObjectState("music");
8
107
    // status glosnikow
8
108
    STATE speakersState = my_data->main_iDomStatus->getObjectState("speakers");
8
109
8
110
    if (musicState != STATE::STOP)
8
111
        my_data->main_iDomTools->MPD_pause();
8
112
    if (speakersState != STATE::ON)
4
113
        my_data->main_iDomTools->turnOnSpeakers();
8
114
    //system
8
115
#ifdef BT_TEST
8
116
    int ret = system("ls");
8
117
#else
118
    int ret = system("runuser -u pi kodi");
119
#endif
8
120
    if(ret != 0)
0
121
    {
0
122
        log_file_mutex.mutex_lock();
0
123
        log_file_cout << CRITICAL<< "kodi zamkniete z błędem "<<ret << std::endl;
0
124
        log_file_mutex.mutex_unlock();
0
125
    }
8
126
    //przywracanie danych
8
127
8
128
    if(musicState == STATE::PLAY)
4
129
        my_data->main_iDomTools->MPD_play(my_data);
8
130
    else
4
131
        my_data->main_iDomTools->turnOffSpeakers();
8
132
    //koniec
8
133
8
134
    my_data->main_iDomStatus->setObjectState("KODI",STATE::DEACTIVE);
8
135
    my_data->mainLCD->set_print_song_state(0);
8
136
    iDOM_THREAD::stop_thread("kodi smartTV",my_data);
8
137
}
138
std::string useful_F::RSHash(const std::string& data, unsigned int b, unsigned int a)
16
139
{
16
140
    time_t act_time;
16
141
    struct tm * act_date;
16
142
    time(&act_time);
16
143
    act_date = localtime(&act_time);
16
144
    char buffer[10];
16
145
    strftime(buffer,10,"%M%H%w",act_date);
16
146
    std::string str(buffer);
16
147
    str+=data;
16
148
    unsigned int hash = 0;
16
149
224
150
    for(std::size_t i = 0; i < str.length(); i++)
208
151
    {
208
152
        hash = hash * a + str[i];
208
153
        a = a * b;
208
154
    }
16
155
    return std::to_string((hash & 0x7FFFFFFF));
16
156
}
157
158
int useful_F::findFreeThreadSlot(std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *array)
16
159
{
92
160
    for (std::size_t i = 0; i< array->size(); ++i)
88
161
    {
88
162
        if (array->at(i).thread_socket == 0)
12
163
            return static_cast<int>(i);
88
164
    }
4
165
    puts("return -1");
4
166
    return -1;
16
167
}
168
169
std::string useful_F::sek_to_uptime(long long secy )
4
170
{
4
171
    const int min = 60; //s
4
172
    const int houry = 3600; //s
4
173
    const int day = 86400; //s
4
174
    int number_day, number_hour, number_min, number_sec;
4
175
    int temp1, temp2, temp3;
4
176
    number_day = secy / day;
4
177
    std::stringstream text;
4
178
    text << "\n" << number_day << " day ";
4
179
    temp1 = secy % day;
4
180
    number_hour = temp1 / houry;
4
181
    text << number_hour << " hours ";
4
182
    temp2 = temp1 % houry;
4
183
    number_min = temp2 / min;
4
184
    text << number_min << " minutes ";
4
185
    temp3 = temp2 % min;
4
186
    number_sec = temp3;
4
187
    text << number_sec << " seconds ";
4
188
    return text.str();
4
189
}
/home/pi/programowanie/iDom_server_OOP/src/functions/tests/functions_BT.cpp
1
#include <gtest/gtest.h>
2
#include "../functions.h"
3
#include "../../RADIO_433_eq/radio_433_eq.h"
4
#include "../../iDomTools/test/iDomTools_fixture.h"
5
6
class functions_fixture : public iDomTOOLS_ClassTest{
7
8
};
9
10
void useful_F::sleep_1min()
44
11
{
44
12
    std::cout << "sleep_1min()"<<std::endl;
44
13
}
14
15
TEST(functions_, tokenizer)
4
16
{
4
17
     std::string test_msg = "one=two three";
4
18
     std::vector<std::string> test_v;
4
19
4
20
     EXPECT_EQ(test_v.size(), 0);
4
21
     useful_F::tokenizer(test_v,"= ",test_msg);
4
22
4
23
     EXPECT_EQ(test_v.size(),3);
4
24
     EXPECT_STREQ(test_v.at(2).c_str(),"three");
4
25
}
26
27
TEST(functions_, sekToUptime)
4
28
{
4
29
    EXPECT_STREQ(useful_F::sek_to_uptime(34534).c_str(),"\n0 day 9 hours 35 minutes 34 seconds ");
4
30
}
31
32
TEST(functions_, tokenizerEmpty)
4
33
{
4
34
     std::string test_msg = "";
4
35
     std::vector<std::string> test_v;
4
36
4
37
     EXPECT_EQ(test_v.size(), 0);
4
38
     EXPECT_THROW(useful_F::tokenizer(test_v,"= ",test_msg),std::string);
4
39
}
40
41
TEST(functions_, removeHtmlTag)
4
42
{
4
43
     std::string test_msg = "<html>test</html>";
4
44
     std::string test_pure_str = useful_F_libs::removeHtmlTag(test_msg);
4
45
4
46
     EXPECT_STREQ(test_pure_str.c_str(),"test");
4
47
}
48
49
TEST(functions_, repalceAll)
4
50
{
4
51
     std::string test_msg = "one two three";
4
52
     std::string test_pure_str = useful_F_libs::replaceAll(test_msg,"two","zero");
4
53
4
54
     EXPECT_STREQ(test_pure_str.c_str(),"one zero three");
4
55
}
56
57
TEST(functions_, split)
4
58
{
4
59
    std::string test_msg = "one two three";
4
60
    std::vector<std::string> test_v;
4
61
4
62
    EXPECT_EQ(test_v.size(), 0);
4
63
    test_v = useful_F::split(test_msg,' ');
4
64
4
65
    EXPECT_EQ(test_v.size(),3);
4
66
    EXPECT_STREQ(test_v.at(2).c_str(),"three");
4
67
}
68
69
TEST(functions_, RSHash)
4
70
{
4
71
    std::string msg = "test msg";
4
72
    std::string s1  = useful_F::RSHash(msg, 33, 44);
4
73
    std::string s2  = useful_F::RSHash(msg, 33 ,44);
4
74
    EXPECT_STREQ(s1.c_str(), s2.c_str());
4
75
4
76
    s1 = useful_F::RSHash(msg, 35, 44);
4
77
    s2 = useful_F::RSHash(msg, 33 ,44);
4
78
    EXPECT_STRNE(s1.c_str(), s2.c_str());
4
79
}
80
81
TEST_F(functions_fixture, setStaticData)
4
82
{
4
83
    test_my_data.sleeper = 99;
4
84
    EXPECT_EQ( useful_F::myStaticData->sleeper, 99 );
4
85
    thread_data test_my_data2;
4
86
    test_my_data2.sleeper = 88;
4
87
    EXPECT_EQ( test_my_data2.sleeper, 88 );
4
88
    EXPECT_EQ( useful_F::myStaticData->sleeper, 99 );
4
89
    useful_F::setStaticData(&test_my_data2);
4
90
    EXPECT_EQ( useful_F::myStaticData->sleeper, 88 );
4
91
}
92
93
TEST_F(functions_fixture, sleepThread)
4
94
{
4
95
    std::array <Thread_array_struc,10> test_THRARRSTR;
4
96
    test_my_data.main_THREAD_arr = &test_THRARRSTR;
4
97
4
98
    MPD_info test_ptr_MPD;
4
99
    test_ptr_MPD.volume = 3;
4
100
    test_my_data.ptr_MPD_info = &test_ptr_MPD;
4
101
4
102
   // RADIO_EQ_CONTAINER_STUB test_rec(&test_my_data);
4
103
    RADIO_EQ_CONTAINER test_rec(&test_my_data);
4
104
    test_rec.loadConfig(test_server_set.radio433MHzConfigFile);
4
105
    test_my_data.main_REC = (&test_rec);
4
106
    test_my_data.alarmTime.time = Clock::getTime();
4
107
    test_my_data.alarmTime.state = STATE::ACTIVE;
4
108
4
109
    RADIO_EQ_CONFIG cfg;
4
110
    cfg.name = "listwa";
4
111
    cfg.ID = "209888";
4
112
    cfg.onCode = "send ON";
4
113
    cfg.offCode= "send OFF";
4
114
    RADIO_EQ* test_RS = new RADIO_SWITCH(&test_my_data,cfg,RADIO_EQ_TYPE::SWITCH);
4
115
    //EXPECT_CALL(test_rec, getEqPointer("listwa")).WillRepeatedly(testing::Return(test_RS));
4
116
4
117
    test_my_data.sleeper = 10;
4
118
4
119
    blockQueue test_q;
4
120
    test_q._clearAll();
4
121
    EXPECT_EQ(test_q._size(),0);
4
122
    useful_F::sleeper_mpd(&test_my_data,"test sleep");
4
123
    EXPECT_EQ(test_q._size(),1);
12
124
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP)<<"NIE ZATRZYMANO MUZYKI :(";
4
125
    delete test_RS;
4
126
}
/home/pi/programowanie/iDom_server_OOP/src/functions/tests/functions_stub.cpp
1
#include "../functions.h"
2
3
void useful_F::clearThreadArray(thread_data *my_data)
32
4
{
32
5
    std::cout << "useful_F::clearThreadArray(thread_data *my_data)" << std::endl;
32
6
}
/home/pi/programowanie/iDom_server_OOP/src/iDomSaveState/../iDomTools/../iDom_server_OOP.h
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
32
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
16
41
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    RADIO_EQ_CONTAINER *main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/home/pi/programowanie/iDom_server_OOP/src/iDomSaveState/../logger/logger.hpp
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
8
84
    {
8
85
        *static_cast<std::ostringstream *>(this) << t;
8
86
        return (*this);
8
87
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/home/pi/programowanie/iDom_server_OOP/src/iDomSaveState/idom_save_state.cpp
1
#include <iostream>     // std::cout
2
#include <fstream>
3
#include "idom_save_state.h"
4
#include "../iDom_server_OOP.h"
5
6
iDom_SAVE_STATE::iDom_SAVE_STATE(const std::string &path): m_path(path)
172
7
{
172
8
#ifdef BT_TEST
172
9
    puts("iDom_SAVE_STATE::iDom_SAVE_STATE()");
172
10
#endif
172
11
}
12
13
iDom_SAVE_STATE::~iDom_SAVE_STATE()
172
14
{
172
15
#ifdef BT_TEST
172
16
    puts("iDom_SAVE_STATE::~iDom_SAVE_STATE()");
172
17
#endif
172
18
}
19
20
nlohmann::json iDom_SAVE_STATE::read()
8
21
{
8
22
    std::lock_guard<std::mutex> lGuard(m_mutex);
8
23
    // read a JSON file
8
24
    std::ifstream i(m_path);
8
25
    nlohmann::json j;
8
26
    i >> j;
8
27
8
28
    log_file_mutex.mutex_lock();
8
29
    log_file_cout << INFO << "czytam zapisany stan parametrow iDom" << std::endl;
8
30
    log_file_mutex.mutex_unlock();
8
31
8
32
    return j;
8
33
}
34
35
void iDom_SAVE_STATE::write(const nlohmann::json &jj)
168
36
{
168
37
    std::lock_guard<std::mutex> lGuard(m_mutex);
168
38
    // write prettified JSON to another file
168
39
    std::ofstream o(m_path);
168
40
    o << std::setw(4) << jj << std::endl;
168
41
}
/home/pi/programowanie/iDom_server_OOP/src/iDomSaveState/test/iDomSaveState_BT.cpp
1
#include <gtest/gtest.h>
2
3
#include "test_data.h"
4
#include "../idom_save_state.h"
5
#include "json.hpp"
6
7
TEST(iDomSaveState, write_and_read)
4
8
{
4
9
    iDom_SAVE_STATE test_saveState("/mnt/ramdisk/iDomStateTest.save");
4
10
    nlohmann::json test_json ;
4
11
4
12
    test_json["happy"] = true;
4
13
    test_json["pi"] = 3.14;
4
14
4
15
    nlohmann::json test_json_in_json;
4
16
    test_json_in_json["name"] = "cyniu";
4
17
    test_json_in_json["age"] = 30;
4
18
4
19
    test_json["person"] = test_json_in_json;
4
20
4
21
    test_saveState.write(test_json);
4
22
    nlohmann::json test_json2 = test_saveState.read();
12
23
    EXPECT_DOUBLE_EQ(test_json.at("pi").get<double>(),
12
24
                     test_json2.at("pi").get<double>()) << "wartosci pi nie sa rowne";
4
25
12
26
    EXPECT_TRUE(test_json2.at("happy").get<bool>()) << " nie jest happy";
4
27
}
/home/pi/programowanie/iDom_server_OOP/src/iDomStatus/idomstatus.cpp
1
#include "idomstatus.h"
2
3
iDomSTATUS::iDomSTATUS()
544
4
{
544
5
}
6
7
void iDomSTATUS::addObject(std::string name, STATE st)
3.22k
8
{
3.22k
9
    std::lock_guard < std::mutex > lock ( m_lockGuard);
3.22k
10
    m_stateMAP.insert(std::make_pair(name,st));
3.22k
11
}
12
13
void iDomSTATUS::setObjectState(const std::string& name, STATE st)
424
14
{
424
15
    std::lock_guard < std::mutex > lock ( m_lockGuard);
424
16
    auto i = m_stateMAP.find(name);
424
17
    if (i != m_stateMAP.end()){
328
18
        i->second = st;
328
19
    }
424
20
    else
96
21
    {
96
22
        lock.~lock_guard();
96
23
        addObject(name,st);
96
24
    }
424
25
}
26
27
STATE iDomSTATUS::getObjectState(const std::string& name)
308
28
{
308
29
    std::lock_guard < std::mutex > lock ( m_lockGuard);
308
30
    auto i = m_stateMAP.find(name);
308
31
    if (i != m_stateMAP.end())
276
32
    {
276
33
        return i->second;
276
34
    }
32
35
    return STATE::UNKNOWN;
308
36
}
37
38
std::string iDomSTATUS::getObjectStateString(const std::string& name)
500
39
{
500
40
    std::lock_guard < std::mutex > lock ( m_lockGuard);
500
41
    auto i = m_stateMAP.find(name);
500
42
    if (i != m_stateMAP.end())
368
43
    {
368
44
        return stateToString( i->second);
368
45
    }
132
46
    return stateToString(STATE::UNKNOWN) + " "+name;
500
47
}
48
49
std::string iDomSTATUS::getAllObjectsStateString()
4
50
{
4
51
    std::stringstream st;
4
52
    st << "state: ";
4
53
    std::lock_guard < std::mutex > lock( m_lockGuard);
4
54
    for (auto elm : m_stateMAP)
32
55
    {
32
56
        st << elm.first << "=";
32
57
        st << stateToString(elm.second) << " ";
32
58
    }
4
59
    return st.str();
4
60
}
/home/pi/programowanie/iDom_server_OOP/src/iDomTools/../../libs/Statistic/statistic.h
1
#ifndef STATISTIC_H
2
#define STATISTIC_H
3
#include <iostream>
4
#include <deque>
5
#include <numeric>
6
#include <algorithm>
7
#include <sstream>
8
#include <cmath>
9
#include <vector>
10
11
template <class T>
12
class STATISTIC
13
{
14
public:
15
    STATISTIC(unsigned int size): m_size(size)
64
16
    {
64
17
64
18
    }
19
    void resize(unsigned int i){
20
        if (i < m_size){
21
            while(m_dequeue.size()> i){
22
                pop_front();
23
            }
24
        }
25
        m_size = i;
26
    }
27
    T size(){
28
        return  static_cast<T>(m_dequeue.size());
29
    }
30
    void push_front(T v){
31
        if (m_dequeue.size() >= m_size){
32
            pop_back();
33
        }
34
        m_dequeue.push_front(v);
35
    }
1.16k
36
    void push_back(T v){
1.16k
37
        if (m_dequeue.size() >= m_size){
0
38
            pop_front();
0
39
        }
1.16k
40
        m_dequeue.push_back(v);
1.16k
41
    }
42
    void pop_back(){
43
        m_dequeue.pop_back();
44
        // std::cout <<"pop_back"<<std::endl;
45
    }
0
46
    void pop_front(){
0
47
        m_dequeue.pop_front();
0
48
        // std::cout <<"pop_front"<<std::endl;
0
49
    }
50
    ///////////////////////////////////////////// statistic /////////////////////////////
32
51
    T median(){
32
52
        auto backup = m_dequeue;
32
53
        std::sort(backup.begin(), backup.end());
32
54
        if (backup.size() % 2 != 0){
8
55
            return backup[backup.size() / 2];
8
56
        }
24
57
        else{
24
58
            T m = backup[backup.size() / 2] + backup[(backup.size() / 2)-1];
24
59
            return m /2;
24
60
        }
32
61
    }
62
    T sum(){
63
        return std::accumulate(m_dequeue.begin(), m_dequeue.end(), static_cast<T>(0));
64
    }
65
66
    T average(){
67
        T av  = sum() /size();
68
        return av;
69
    }
70
71
    T max(){
72
        T max = m_dequeue[0];
73
        for (auto v : m_dequeue){
74
            if (v > max){
75
                max = v;
76
            }
77
        }
78
        return max;
79
    }
80
81
    T min(){
82
        T min = m_dequeue[0];
83
        for (auto v : m_dequeue){
84
            if (v < min){
85
                min = v;
86
            }
87
        }
88
        return min;
89
    }
90
91
    T range(){
92
        return max() - min();
93
    }
94
95
    T standardDeviation(){
96
        double standardDeviation = 0.0;
97
        T _av = average();
98
99
        for(int i = 0; i < size(); ++i){
100
            standardDeviation += pow(m_dequeue.at(i) - _av, 2);
101
        }
102
        return sqrt(standardDeviation / size());
103
    }
104
105
    T coefficientOfVariation(){
106
107
        return (standardDeviation()/average()) /** 100*/;
108
    }
109
32
110
    T mode(){
32
111
32
112
        T _mode = 0;
32
113
        T _modeTemp = 0;
32
114
        int counter = 1;
32
115
        int modeCounter = 1;
32
116
        auto backup = m_dequeue;
32
117
        if(m_dequeue.size() == 1)
8
118
        {
8
119
            return m_dequeue.at(0);
8
120
        }
24
121
        std::sort(backup.begin(), backup.end());
24
122
#ifdef BT_TEST
24
123
        std::cout << " " << std::endl;
24
124
        for (auto i : backup)
576
125
        {
576
126
            std::cout << i << " ";
576
127
        }
24
128
        std::cout << " " << std::endl;
24
129
#endif
24
130
        _mode = _modeTemp = backup.at(0);
24
131
        backup.pop_front();
24
132
        for (auto b : backup)
552
133
        {
552
134
            if (_modeTemp == b)
480
135
            {
480
136
                modeCounter++;
480
137
            }
552
138
            else
72
139
            {
72
140
                _modeTemp = b;
72
141
                modeCounter = 1;
72
142
            }
552
143
552
144
            if(counter < modeCounter)
288
145
            {
288
146
                counter = modeCounter;
288
147
                _mode = _modeTemp;
288
148
            }
552
149
        }
24
150
#ifdef BT_TEST
24
151
        std::cout << " moda: " << _mode << " wystepuje razy " << counter << std::endl;
24
152
#endif
24
153
        return _mode;
32
154
    }
155
156
    float trend(){
157
        int down = 0;
158
        int eq = 0;
159
        int up = 0;
160
        int lp = 0;
161
        T diff = 0;
162
        T first = m_dequeue[0];
163
164
        for (auto i = 1; i < m_dequeue.size(); ++i){
165
            if (first < m_dequeue[i]){
166
                up++;
167
                if (m_dequeue[i] - first > diff){
168
                    diff = m_dequeue[i] - first;
169
                    lp = i;
170
                }
171
            }
172
            if (first == m_dequeue[i]){ eq++;}
173
            if (first > m_dequeue[i]){
174
                if (diff < first - m_dequeue[i] ){
175
                    diff = first - m_dequeue[i];
176
                    lp = i;
177
                }
178
                down++;
179
            }
180
            first = m_dequeue[i];
181
        }
182
        std::cout <<"up "<<up<<" eq "<< eq << " down "<< down <<" max diff "<< diff<<" lp "<<lp << std::endl;
183
        return 2.2;
184
    }
185
186
    bool isMoreDiff(T diff){
187
        if (m_dequeue.size()>2){
188
            T d = m_dequeue.at( m_dequeue.size()-2)
189
                    - m_dequeue.at( m_dequeue.size() - 1);
190
            d = fabs(d);
191
            if (d > diff && m_alarm == false){
192
                m_alarm = true;
193
                return true;
194
            }
195
            if (d <= diff){
196
                m_alarm = false;
197
                return false;
198
            }
199
        }
200
        return false;
201
    }
202
    std::pair<double,double> getLast2(){
203
        if (m_dequeue.size()>2){
204
            return std::make_pair(static_cast<double>(m_dequeue.at( m_dequeue.size()-2)),
205
                                  static_cast<double>(m_dequeue.at( m_dequeue.size()-1))    );
206
        }
207
#ifdef BT_TEST
208
        puts("no data - return 0.0 0.0");
209
#endif
210
        return std::make_pair(0.0,0.0);
211
    }
212
213
    /////////////////////////////////////////////////////////////////////////////////////
214
    void print(){
215
        for(auto n : m_dequeue){
216
            std::cout << ","<< n;
217
        }
218
        std::cout << " " <<std::endl;
219
    }
220
221
222
    std::string stats(){
223
224
        std::stringstream ss(" brak danych =(");
225
        if(size()>0)
226
        {
227
            ss.str("");
228
            ss <<"rozmiar tablicy: "<< size() <<std::endl
229
              << "min: "<< min() <<std::endl
230
              << "max: "<< max()<<std::endl
231
              << "srednia " << average() <<std::endl
232
              << "mediana " << median()  <<std::endl
233
              << "odchylenie st "<< standardDeviation() << std::endl
234
              << "wspolczynnik zmiennosci " << coefficientOfVariation() <<"%"<< std::endl
235
              << "Dominanta " << mode();
236
237
238
            ss << std::endl
239
               << "data " <<  std::endl;
240
            for(auto n : m_dequeue){
241
                ss << "|"<< n;
242
            }
243
        }
244
        ss <<  std::endl;
245
        return ss.str();
246
    }
247
248
private:
249
    unsigned int m_size;
250
    std::deque <T> m_dequeue;
251
    bool m_alarm = false;
252
};
253
254
#endif // STATISTIC_H
/home/pi/programowanie/iDom_server_OOP/src/iDomTools/../../libs/useful/useful.h
1
#ifndef Iusefull_H
2
#define Iusefull_H
3
4
#include <iostream>
5
#include <string>
6
#include <vector>
7
#include <ostream>
8
#include <chrono>
9
#include <sstream>
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <iomanip>
13
#ifndef ANDROID
14
#include "json.hpp"
15
#endif
16
17
std::vector<std::string> split_string(const std::string& s, char separator );
18
19
class useful_F_libs {
20
public:
21
    static  void write_to_mkfifo(const std::string& path, const std::string &msg);
22
    static  std::string read_from_mkfifo(const std::string &path);
23
    static size_t  WriteCallback(void *contents, size_t size, size_t nmemb, void *userp);
24
    static std::string find_tag (const std::string &temp);
25
    //////////////////// HTTP req //////////////////////////
26
    static std::string httpPost(const std::string &url, int timeoutSeconds);
27
    static std::string httpPost(const std::string &url);
28
    static void downloadFile(const std::string &url, const std::string &path, int timeoutSeconds);
29
    static std::string replaceAll(std::string str, const std::string& from, const std::string& to);
30
    static std::string removeHtmlTag(std::string &data);
31
    /////////////////////  JSON ////////////////////////////
32
33
#ifndef ANDROID
34
    static nlohmann::json getJson(const std::string &url);
35
#endif
36
};
37
namespace std
38
{
39
40
#ifdef ANDROID
41
template <typename T>
42
int stoi(T s){
43
    return atoi(s.c_str());
44
}
45
#endif
46
47
template <typename T>
48
std::string to_string(T value)
49
{
50
    std::ostringstream os;
51
    os << value;
52
    return os.str();
53
}
54
} // namespace std
55
56
template <typename T>
57
std::string to_string_with_precision(const T a_value, const int n = 4)
68
58
{
68
59
    std::ostringstream out;
68
60
    out << std::setprecision(n) << a_value;
68
61
    return out.str();
68
62
}
63
64
struct Clock{
65
private:
66
    std::time_t m_time;
67
#ifdef BT_TEST
68
    static unsigned int m_BT_H;
69
    static unsigned int m_BT_M;
70
#endif
71
public:
72
    unsigned int m_h = 0;
73
    unsigned int m_min = 0;
74
    Clock () {}
75
    Clock(std::string t){
76
        std::vector<std::string> vt = split_string(t,':');
77
        int h = std::stoi(vt.at(0));
78
        int m = std::stoi(vt.at(1));
79
        set(static_cast <unsigned int>(h),static_cast <unsigned int>(m));
80
    }
81
82
    Clock(unsigned int h, unsigned int m) {
83
        set(h,m);
84
    }
85
    /////////////////////////////////////////////////////////////////////////////////////
86
    void set(unsigned int h, unsigned int m){
87
        if (h<24 && m <60){
88
            this->m_h = h;
89
            this->m_min = m;
90
        }
91
        else {
92
            throw 0;
93
        }
94
    }
95
96
    /////////////////////////////////////////////////////////////////////////////////////
97
    const std::string getString(){
98
        std::stringstream ret;
99
        if (m_h < 10) {
100
            ret << "0";
101
        }
102
        ret << m_h;
103
        ret << ":";
104
        if (m_min < 10) {
105
            ret << "0";
106
        }
107
        ret << m_min;
108
        return ret.str();
109
    }
110
    /////////////////////////////////////////////////////////////////////////////////////
111
    bool operator == (const Clock & c){
112
        if ((this->m_h == c.m_h) && (this->m_min == c.m_min)){
113
            return true;
114
        }
115
        else{
116
            return false;
117
        }
118
    }
119
    /////////////////////////////////////////////////////////////////////////////////////
120
    bool operator != (const Clock & c){
121
        if ((this->m_h != c.m_h) || (this->m_min != c.m_min)){
122
            return true;
123
        }
124
        else{
125
            return false;
126
        }
127
    }
128
    /////////////////////////////////////////////////////////////////////////////////////
129
    friend std::ostream & operator<< (std::ostream &w ,  Clock &c) {
130
        return w << c.getString();
131
    }
132
    /////////////////////////////////////////////////////////////////////////////////////
133
    bool operator < (const Clock& c){
134
        if (this->m_h < c.m_h){
135
            return true;
136
        }
137
        else{
138
            if (this->m_h == c.m_h && this->m_min < c.m_min){
139
                return true;
140
            }
141
        }
142
        return false;
143
    }
144
    /////////////////////////////////////////////////////////////////////////////////////
145
    bool operator > (const Clock& c){
146
        if (this->m_h > c.m_h){
147
            return true;
148
        }
149
        else{
150
            if (this->m_h == c.m_h && this->m_min > c.m_min){
151
                return true;
152
            }
153
        }
154
        return false;
155
    }
156
    /////////////////////////////////////////////////////////////////////////////////////
157
    bool operator >= (const Clock& c){
158
        if (this->m_h > c.m_h){
159
            return true;
160
        }
161
        else if (this->m_h == c.m_h){
162
163
            if (this->m_min >= c.m_min){
164
                return true;
165
            }
166
        }
167
        return false;
168
    }
169
    /////////////////////////////////////////////////////////////////////////////////////
170
    bool operator <= (const Clock& c){
171
        if (this->m_h < c.m_h){
172
            return true;
173
        }
174
        else if (this->m_h == c.m_h){
175
176
            if (this->m_min <= c.m_min){
177
                return true;
178
            }
179
        }
180
        return false;
181
    }
182
    /////////////////////////////////////////////////////////////////////////////////////
183
    Clock  operator + (const Clock& c){
184
        unsigned int minutes, hours;
185
        minutes = m_min+ c.m_min;
186
        hours = m_h + c.m_h;
187
        if (minutes >59){
188
            minutes =  minutes % 60;
189
            hours+=1;
190
        }
191
        if (hours >= 24){
192
            hours-=24;
193
        }
194
        return  Clock(hours, minutes);
195
196
    }
197
    /////////////////////////////////////////////////////////////////////////////////////
198
    Clock&  operator += (const Clock& c){
199
        unsigned int minutes, hours;
200
        minutes = m_min+ c.m_min;
201
        hours = m_h + c.m_h;
202
        if (minutes >59){
203
            minutes =  minutes % 60;
204
            hours+=1;
205
        }
206
        if (hours >= 24){
207
            hours-=24;
208
        }
209
        this->m_h = hours;
210
        this->m_min = minutes;
211
        return *this;
212
213
    }
214
    /////////////////////////////////////////////////////////////////////////////////////
215
216
    unsigned int toSeconds(){
217
        return toSeconds(Clock(this->m_h, this->m_min) );
218
    }
219
    /////////////////////////////////////////////////////////////////////////////////////
220
221
    static unsigned int toSeconds(Clock t){
222
        return ((t.m_h*60) + t.m_min)*60;
223
    }
224
    /////////////////////////////////////////////////////////////////////////////////////
225
226
    static Clock fromSeconds(unsigned int sec){
227
        unsigned int h = sec/3600;
228
        unsigned int min = sec%3600;
229
        min = min/60;
230
        return Clock(h,min);
231
    }
232
    /////////////////////////////////////////////////////////////////////////////////////
233
234
    static Clock periodOfTime(Clock start, Clock end)
235
    {
236
        if (end >= start){
237
            return Clock::fromSeconds(end.toSeconds() - start.toSeconds()  );
238
        }
239
        else{
240
            return Clock::fromSeconds(end.toSeconds() + ( Clock::toSeconds(Clock(23,59))+ 60 - start.toSeconds() ) );
241
        }
242
        //return diff;
243
    }
244
    ////////////////////////////////////////////////////////////////////////////////////
245
    static unsigned int getUnixTime()
246
    {
247
        return static_cast<unsigned int> (std::time(nullptr));
248
    }
249
    /////////////////////////////////////////////////////////////////////////////////////
250
#ifdef BT_TEST
251
    static void setTime_forBT_usage(int h, int m)
252
    {
253
        m_BT_H = h;
254
        m_BT_M = m;
255
    }
256
#endif
257
    /////////////////////////////////////////////////////////////////////////////////////
258
    static Clock getTime()
259
    {
260
#ifdef BT_TEST
261
        return Clock(m_BT_H,m_BT_M);
262
#else
263
        time_t now = time(0);
264
        tm *ltm = localtime(&now);
265
        return Clock( static_cast <unsigned int>(ltm->tm_hour),static_cast <unsigned int>(ltm->tm_min) );
266
#endif
267
    }
268
    /////////////////////////////////////////////////////////////////////////////////////
269
    void stopwatchStart()
270
    {
271
        m_time = std::time(nullptr);
272
    }
273
    /////////////////////////////////////////////////////////////////////////////////////
274
    unsigned int  stopwatchStopAndGetResult()
275
    {
276
        return static_cast<unsigned int>(std::time(nullptr) - m_time);
277
    }
278
};
279
280
enum class STATE {
281
    OFF,
282
    ON,
283
    UNKNOWN,
284
    PLAY,
285
    PAUSE,
286
    STOP,
287
    ACTIVE,
288
    DEACTIVE,
289
    WORKING,
290
    DEFINE,
291
    UNDEFINE,
292
    LOCK,
293
    UNLOCK,
294
    EMPTY,
295
    FULL,
296
    SEND_OK,
297
    SEND_NOK
298
    //WARNING remember add new state to stateToString() usefull.cpp
299
};
300
301
302
std::string stateToString(STATE s);
303
STATE stringToState(const std::string& s);
304
305
#endif
/home/pi/programowanie/iDom_server_OOP/src/iDomTools/../thread_functions/../iDom_server_OOP.h
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
472
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
232
41
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    RADIO_EQ_CONTAINER *main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/home/pi/programowanie/iDom_server_OOP/src/iDomTools/../thread_functions/../logger/logger.hpp
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
268
84
    {
268
85
        *static_cast<std::ostringstream *>(this) << t;
268
86
        return (*this);
268
87
    }
_ZN6LoggerlsINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEERS_RKT_
236
84
    {
236
85
        *static_cast<std::ostringstream *>(this) << t;
236
86
        return (*this);
236
87
    }
_ZN6LoggerlsIA28_cEERS_RKT_
16
84
    {
16
85
        *static_cast<std::ostringstream *>(this) << t;
16
86
        return (*this);
16
87
    }
_ZN6LoggerlsIA32_cEERS_RKT_
12
84
    {
12
85
        *static_cast<std::ostringstream *>(this) << t;
12
86
        return (*this);
12
87
    }
_ZN6LoggerlsIA36_cEERS_RKT_
0
84
    {
0
85
        *static_cast<std::ostringstream *>(this) << t;
0
86
        return (*this);
0
87
    }
_ZN6LoggerlsIA47_cEERS_RKT_
4
84
    {
4
85
        *static_cast<std::ostringstream *>(this) << t;
4
86
        return (*this);
4
87
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/home/pi/programowanie/iDom_server_OOP/src/iDomTools/idomtools.cpp
1
#include <algorithm>
2
#include <fstream>
3
#include <string>
4
#include <typeinfo>
5
6
#include "idomtools.h"
7
#include "../functions/functions.h"
8
#include "../../libs/emoji/emoji.h"
9
#include "../../libs/Statistic/statistic.h"
10
#include "../CRON/cron.hpp"
11
#include "../RADIO_433_eq/radio_433_eq.h"
12
#include "json.hpp"
13
#include "../thread_functions/iDom_thread.h"
14
15
iDomTOOLS::iDomTOOLS(thread_data *myData): key(myData->server_settings->TS_KEY)
520
16
{
520
17
    puts("iDomTOOLS::iDomTOOLS()");
520
18
    my_data = myData;
520
19
520
20
    //////////////////////////////////// temeprature /////////////////
520
21
520
22
    allThermometer.add("inside");
520
23
    allThermometer.add("outside");
520
24
    allThermometerUpdate.add("inside");
520
25
    allThermometerUpdate.add("outside");
520
26
    /////////////////////////////////////////////////////////////////
520
27
#ifndef BT_TEST
28
    pinMode(iDomConst::GPIO_SPIK, OUTPUT); // gpio pin do zasilania glosnikow
29
    digitalWrite(iDomConst::GPIO_SPIK,LOW);
30
    pinMode(iDomConst::GPIO_PRINTER,OUTPUT); /// gpio pin do zsilania drukarki
31
    digitalWrite(iDomConst::GPIO_PRINTER,LOW);
32
    pinMode(iDomConst::BUTTON_PIN, INPUT); // gpio pin przycisku
33
34
    if (wiringPiISR (iDomConst::BUTTON_PIN, INT_EDGE_BOTH, &useful_F::button_interrupt) < 0 ) {
35
36
        log_file_cout.mutex_lock();
37
        log_file_cout << CRITICAL <<"Unable to setup ISR RISING "<<std::endl;
38
        log_file_cout.mutex_unlock();
39
40
    }
41
#endif
520
42
    my_data->main_iDomStatus->addObject("cameraLED",STATE::UNKNOWN);
520
43
    my_data->main_iDomStatus->addObject("printer",STATE::OFF);
520
44
    my_data->main_iDomStatus->addObject("speakers",STATE::OFF);
520
45
    my_data->main_iDomStatus->addObject("alarm",STATE::DEACTIVE);
520
46
    my_data->main_iDomStatus->addObject("KODI",STATE::DEACTIVE);
520
47
520
48
    ///////// setup viber api
520
49
    m_viber.setAvatar(my_data->server_settings->viberAvatar);
520
50
    m_viber.setAccessToken(my_data->server_settings->viberToken);
520
51
    m_viber.setURL("https://chatapi.viber.com/pa/send_message");
520
52
    ///////// setup faceboook api
520
53
    m_facebook.setAccessToken(my_data->server_settings->facebookAccessToken);
520
54
520
55
    //////// button 433MHz
520
56
    buttonPointerVector = my_data->main_REC->getButtonPointerVector();
520
57
520
58
    lastButton433MHzLockUnlockTime = Clock::getTime() + Clock(23,58);
520
59
520
60
}
61
62
TEMPERATURE_STATE iDomTOOLS::hasTemperatureChange(const std::string& thermometerName, double reference, double histereza )
56
63
{
56
64
    reference += 0.0055;
56
65
    const auto newTemp = allThermometer.getTemp(thermometerName);
56
66
    const auto oldTemp = allThermometer.getOldTemp(thermometerName);
56
67
    const auto lastState = allThermometer.getLastState(thermometerName);
56
68
    if (newTemp >= reference + histereza &&
24
69
            oldTemp < reference + histereza &&
12
70
            lastState != TEMPERATURE_STATE::Over)
12
71
    {
12
72
        my_data->myEventHandler.run("test")->addEvent("over: new "+ to_string_with_precision(newTemp)+" old: "
12
73
                                                      +to_string_with_precision(oldTemp)+" ref: "
12
74
                                                      +to_string_with_precision(reference));
12
75
        allThermometer.setState(thermometerName, TEMPERATURE_STATE::Over);
12
76
        return TEMPERATURE_STATE::Over;
12
77
    }
44
78
    else if (newTemp <= reference - histereza &&
28
79
             oldTemp > reference - histereza &&
12
80
             lastState != TEMPERATURE_STATE::Under)
12
81
    {
12
82
        my_data->myEventHandler.run("test")->addEvent("under: new "+to_string_with_precision(newTemp)+" old: "
12
83
                                                      +to_string_with_precision(oldTemp)+" ref: "
12
84
                                                      +to_string_with_precision(reference));
12
85
        allThermometer.setState(thermometerName, TEMPERATURE_STATE::Under);
12
86
        return TEMPERATURE_STATE::Under;
12
87
    }
56
88
32
89
    my_data->myEventHandler.run("test")->addEvent("noChanges: new "+to_string_with_precision(newTemp)+" old: "
32
90
                                                  +to_string_with_precision(oldTemp)+" ref: "+to_string_with_precision(reference));
32
91
32
92
    allThermometer.setState(thermometerName, TEMPERATURE_STATE::NoChanges);
32
93
    return TEMPERATURE_STATE::NoChanges;
56
94
}
95
96
void iDomTOOLS::sendSMSifTempChanged(const std::string& thermomethernName, int reference)
56
97
{
56
98
    TEMPERATURE_STATE status = hasTemperatureChange(thermomethernName,reference,0.5);
56
99
    std::string m = "temperature "+thermomethernName+" over "+ EMOJI::emoji(E_emoji::NORTH_EAST_ARROW)
56
100
            + to_string_with_precision(reference);
56
101
56
102
    if (status == TEMPERATURE_STATE::Over){
12
103
        my_data->myEventHandler.run("temperature")->addEvent(m);
12
104
        if (reference < 2){
4
105
            sendViberMsg(m,my_data->server_settings->viberReceiver.at(0),my_data->server_settings->viberSender);
4
106
            sendViberMsg(m,my_data->server_settings->viberReceiver.at(1),my_data->server_settings->viberSender);
4
107
        }
8
108
        else{
8
109
            sendViberMsg(m,my_data->server_settings->viberReceiver.at(0),my_data->server_settings->viberSender);
8
110
        }
12
111
    }
44
112
    else if (status == TEMPERATURE_STATE::Under){
12
113
        m ="temperature " + thermomethernName+" under "+EMOJI::emoji(E_emoji::SOUTH_EAST_ARROW)
12
114
                +to_string_with_precision(reference);
12
115
        my_data->myEventHandler.run("temperature")->addEvent(m);
12
116
        if (reference < 2){
8
117
            sendViberPicture(m,"http://canacopegdl.com/images/cold/cold-14.jpg",
8
118
                             my_data->server_settings->viberReceiver.at(0),
8
119
                             my_data->server_settings->viberSender);
8
120
            sendViberPicture(m,"http://canacopegdl.com/images/cold/cold-14.jpg",
8
121
                             my_data->server_settings->viberReceiver.at(1),
8
122
                             my_data->server_settings->viberSender);
8
123
            postOnFacebook(m,"http://canacopegdl.com/images/cold/cold-14.jpg");
8
124
        }
4
125
        else {
4
126
            sendViberMsg(m,my_data->server_settings->viberReceiver.at(0),
4
127
                         my_data->server_settings->viberSender);
4
128
        }
12
129
    }
32
130
    else{
32
131
        //my_data->myEventHandler.run("unknown")->addEvent("temperatura nie przeszla przez "+to_string_with_precision(reference));
32
132
    }
56
133
}
134
135
std::string iDomTOOLS::getThermoStats(const std::string& name)
8
136
{
8
137
    return allThermometerUpdate.getStatsByName(name);
8
138
}
139
140
void iDomTOOLS::updateTemperatureStats()
24
141
{
24
142
    auto v = getTemperature();
24
143
    allThermometerUpdate.updateAll(&v);
24
144
    allThermometerUpdate.updateStats("outside");
24
145
    allThermometerUpdate.updateStats("inside");
24
146
24
147
    if( true == allThermometerUpdate.isMoreDiff("outside",2.1)){
8
148
        auto data = allThermometerUpdate.getLast2("outside");
8
149
        std::string msg = "alarm roznicy temeratur na polu! " + to_string_with_precision(data.first) +" na "+
8
150
                to_string_with_precision(data.second);
8
151
8
152
        if (data.first > data.second){
4
153
            msg += " temperatura maleje " + EMOJI::emoji(E_emoji::CHART_WITH_DOWNWARDS_TREND);
4
154
        }
4
155
        else{
4
156
            msg += " temperatura rośnie " + EMOJI::emoji(E_emoji::CHART_WITH_UPWARDS_TREND);
4
157
        }
8
158
8
159
        sendViberMsg(msg,
8
160
                     my_data->server_settings->viberReceiver.at(0),
8
161
                     my_data->server_settings->viberSender);
8
162
8
163
        log_file_mutex.mutex_lock();
8
164
        log_file_cout << WARNING << msg << std::endl;
8
165
        log_file_mutex.mutex_unlock();
8
166
    }
24
167
    if( true == allThermometerUpdate.isMoreDiff("inside",2.1)){
8
168
        auto data = allThermometerUpdate.getLast2("inside");
8
169
        std::string msg = "alarm roznicy temeratur na mieszkaniu! " + to_string_with_precision(data.first) +" na "+
8
170
                to_string_with_precision(data.second);
8
171
8
172
        if (data.first > data.second){
4
173
            msg += " temperatura maleje " + EMOJI::emoji(E_emoji::CHART_WITH_DOWNWARDS_TREND);
4
174
        }
4
175
        else{
4
176
            msg += " temperatura rośnie " + EMOJI::emoji(E_emoji::CHART_WITH_UPWARDS_TREND);
4
177
        }
8
178
8
179
        sendViberMsg(msg,
8
180
                     my_data->server_settings->viberReceiver.at(0),
8
181
                     my_data->server_settings->viberSender);
8
182
8
183
        log_file_mutex.mutex_lock();
8
184
        log_file_cout << WARNING << msg << std::endl;
8
185
        log_file_mutex.mutex_unlock();
8
186
    }
24
187
}
188
189
void iDomTOOLS::turnOnSpeakers()
32
190
{
32
191
    if (useful_F::myStaticData->idom_all_state.houseState == STATE::UNLOCK)
16
192
    {
16
193
        digitalWrite(iDomConst::GPIO_SPIK, HIGH);
16
194
        useful_F::myStaticData->main_iDomStatus->setObjectState("speakers",STATE::ON);
16
195
    }
16
196
    else{
16
197
        useful_F::myStaticData->myEventHandler.run("speakers")->addEvent("speakers can not start due to home state: "+
16
198
                                                                         stateToString(useful_F::myStaticData->idom_all_state.houseState));
16
199
    }
32
200
    useful_F::myStaticData->main_iDomTools->saveState_iDom();
32
201
}
202
203
void iDomTOOLS::turnOffSpeakers()
24
204
{
24
205
    digitalWrite(iDomConst::GPIO_SPIK, LOW);
24
206
    useful_F::myStaticData->main_iDomStatus->setObjectState("speakers",STATE::OFF);
24
207
    // useful_F::myStaticData->main_iDomTools->saveState_iDom();
24
208
}
209
210
void iDomTOOLS::turnOnPrinter()
20
211
{
20
212
    if (my_data->idom_all_state.houseState == STATE::UNLOCK)
16
213
    {
16
214
        digitalWrite(iDomConst::GPIO_PRINTER,HIGH);
16
215
        my_data->myEventHandler.run("230V")->addEvent("230v drukarki ON");
16
216
        my_data->main_iDomStatus->setObjectState("printer",STATE::ON);
16
217
    }
4
218
    else{
4
219
        my_data->myEventHandler.run("230V")->addEvent("Printer can not start due to home state: "+
4
220
                                                      stateToString(my_data->idom_all_state.houseState));
4
221
    }
20
222
}
223
224
void iDomTOOLS::turnOffPrinter()
24
225
{
24
226
    digitalWrite(iDomConst::GPIO_PRINTER,LOW);
24
227
    my_data->myEventHandler.run("230V")->addEvent("230v drukarki OFF");
24
228
    my_data->main_iDomStatus->setObjectState("printer",STATE::OFF);
24
229
}
230
231
PIN_STATE iDomTOOLS::getPinState(int pin_number)
28
232
{
28
233
    int pin_state = digitalRead(pin_number);
0
234
    switch (pin_state){
12
235
    case 0:
12
236
        return PIN_STATE::LOW_STATE;
8
237
    case 1:
8
238
        return PIN_STATE::HIGH_STATE;
8
239
    default:
8
240
        return PIN_STATE::UNKNOWN_STATE;
0
241
    }
28
242
}
243
244
void iDomTOOLS::turnOnOffPrinter()
16
245
{
16
246
    PIN_STATE pinState = getPinState(iDomConst::GPIO_PRINTER);
16
247
    switch (pinState){
4
248
    case PIN_STATE::HIGH_STATE:
4
249
        turnOffPrinter();
4
250
        my_data->mainLCD->set_lcd_STATE(10);
4
251
        my_data->mainLCD->printString(true,0,0,"230V OFF");
4
252
        break;
8
253
    case PIN_STATE::LOW_STATE:
8
254
        turnOnPrinter();
8
255
        my_data->mainLCD->set_lcd_STATE(10);
8
256
        my_data->mainLCD->printString(true,0,0,"230V ON");
8
257
        break;
4
258
    default:
4
259
        puts("def");
4
260
4
261
        log_file_mutex.mutex_lock();
4
262
        log_file_cout << CRITICAL << " blad odczytu stanu pinu zasilania drukarki "<< std::endl;
4
263
        log_file_mutex.mutex_unlock();
16
264
    }
16
265
}
266
267
void iDomTOOLS::turnOnOff433MHzSwitch(const std::string& name)
16
268
{
16
269
    STATE listwaState = my_data->main_iDomStatus->getObjectState(name);
16
270
    RADIO_SWITCH *m_switch = dynamic_cast<RADIO_SWITCH*>(my_data->main_REC->getEqPointer(name));
16
271
    if (listwaState == STATE::ON){
8
272
        my_data->mainLCD->set_lcd_STATE(10);
8
273
        my_data->mainLCD->printString(true,0,0,"230V OFF "+name);
8
274
        m_switch->off();
8
275
    }
8
276
    else if (listwaState == STATE::OFF){
8
277
        my_data->mainLCD->set_lcd_STATE(10);
8
278
        my_data->mainLCD->printString(true,0,0,"230V ON "+name);
8
279
        m_switch->on();
8
280
    }
16
281
    saveState_iDom();
16
282
}
283
284
void iDomTOOLS::turnOn433MHzSwitch(std::string name)
4
285
{
4
286
    RADIO_SWITCH *m_switch = dynamic_cast<RADIO_SWITCH*>(my_data->main_REC->getEqPointer(std::move(name)));
4
287
    m_switch->on();
4
288
    //saveState_iDom();
4
289
}
290
291
void iDomTOOLS::turnOff433MHzSwitch(std::string name)
12
292
{
12
293
    RADIO_SWITCH *m_switch = dynamic_cast<RADIO_SWITCH*>(my_data->main_REC->getEqPointer(std::move(name)));
12
294
    m_switch->off();
12
295
}
296
297
void iDomTOOLS::runOnSunset()
12
298
{
12
299
    if (my_data->idom_all_state.houseState == STATE::UNLOCK)
8
300
    {
8
301
        ////switch 433mhz
40
302
        for (auto m_switch : my_data->main_REC->getSwitchPointerVector()){
40
303
            m_switch->onSunset();
40
304
        }
8
305
    }
4
306
    else{
4
307
        my_data->myEventHandler.run("iDom")->addEvent("433MHz can not start due to home state: "+
4
308
                                                      stateToString(my_data->idom_all_state.houseState));
4
309
    }
12
310
}
311
312
void iDomTOOLS::runOnSunrise()
12
313
{
12
314
    if (my_data->idom_all_state.houseState == STATE::UNLOCK)
8
315
    {
8
316
        ////switch 433mhz
40
317
        for (auto m_switch : my_data->main_REC->getSwitchPointerVector()){
40
318
            m_switch->onSunrise();
40
319
        }
8
320
    }
4
321
    else{
4
322
        my_data->myEventHandler.run("iDom")->addEvent("433MHz can not start due to home state: "+
4
323
                                                      stateToString(my_data->idom_all_state.houseState));
4
324
    }
12
325
    my_data->main_iDomTools->ledOFF();
12
326
}
327
328
void iDomTOOLS::lockHome()
28
329
{
28
330
    my_data->idom_all_state.houseState = STATE::LOCK;
28
331
    my_data->main_iDomStatus->setObjectState("house", STATE::LOCK);
28
332
    my_data->main_iDomTools->sendViberPicture("dom zablokownay!",
28
333
                                              "http://cyniu88.no-ip.pl/images/iDom/iDom/lock.jpg",
28
334
                                              my_data->server_settings->viberReceiver.at(0),
28
335
                                              my_data->server_settings->viberSender);
28
336
28
337
    log_file_mutex.mutex_lock();
28
338
    log_file_cout << INFO << "status domu - "+stateToString(my_data->idom_all_state.houseState)<< std::endl;
28
339
    log_file_mutex.mutex_unlock();
28
340
28
341
    saveState_iDom();
28
342
}
343
344
void iDomTOOLS::unlockHome()
56
345
{
56
346
    my_data->idom_all_state.houseState = STATE::UNLOCK;
56
347
    my_data->main_iDomStatus->setObjectState("house", STATE::UNLOCK);
56
348
    my_data->main_iDomTools->sendViberPicture("dom odblokownay!",
56
349
                                              "http://cyniu88.no-ip.pl/images/iDom/iDom/unlock.jpg",
56
350
                                              my_data->server_settings->viberReceiver.at(0),
56
351
                                              my_data->server_settings->viberSender);
56
352
56
353
    log_file_mutex.mutex_lock();
56
354
    log_file_cout << INFO << "status domu - "+stateToString(my_data->idom_all_state.houseState)<< std::endl;
56
355
    log_file_mutex.mutex_unlock();
56
356
56
357
    saveState_iDom();
56
358
}
359
360
void iDomTOOLS::switchActionOnLockHome()
4
361
{
4
362
    ////switch 433mhz
20
363
    for (auto m_switch : my_data->main_REC->getSwitchPointerVector()){
20
364
        m_switch->onLockHome();
20
365
    }
4
366
}
367
368
void iDomTOOLS::switchActionOnUnlockHome()
4
369
{
4
370
    ////switch 433mhz
20
371
    for (auto m_switch : my_data->main_REC->getSwitchPointerVector()){
20
372
        m_switch->onUnlockHome();
20
373
    }
4
374
}
375
376
std::string iDomTOOLS::buttonPressed(const std::string& id)
8
377
{
8
378
    for (auto n : buttonPointerVector){
8
379
        if (id == n->getID()){
4
380
            return n->getName();
4
381
        }
8
382
    }
4
383
    throw "UNKNOWN BUTTON ID: " + std::to_string(id);
8
384
}
385
386
void iDomTOOLS::button433MHzPressedAction(const std::string& name)
16
387
{
16
388
    if (name == "locker"){
16
389
        RADIO_BUTTON* buttonLocker = static_cast<RADIO_BUTTON*>(my_data->main_REC->getEqPointer(name) );
16
390
        button433mhzLockerPressed(buttonLocker);
16
391
    }
16
392
}
393
394
void iDomTOOLS::button433mhzLockerPressed(RADIO_BUTTON *radioButton)
40
395
{
40
396
    static unsigned int counter = 0;
40
397
40
398
    Clock t = Clock::getTime();
40
399
    if (lastButton433MHzLockUnlockTime != t /*|| (lastButton433MHzLockUnlockTime + Clock(0,1)) == t*/)
24
400
    {
24
401
#ifdef BT_TEST
24
402
        std::cout << "LOCKER TEST iDomTOOLS::button433mhzLockerPressed()" <<std::endl;
24
403
#endif
24
404
        lastButton433MHzLockUnlockTime = t;
24
405
        counter = 0;
24
406
        if(my_data->idom_all_state.houseState != STATE::UNLOCK)
8
407
        {
8
408
            buttonUnlockHome();
8
409
            puts("\nodblokuje dom\n");
8
410
            radioButton->setState(STATE::UNLOCK);
8
411
        }
16
412
        else if (my_data->main_iDomStatus->getObjectState("music") == STATE::PLAY)
4
413
        {
4
414
            ledOFF();
4
415
            MPD_stop();
4
416
            turnOffPrinter();
4
417
            radioButton->setState(STATE::STOP);
4
418
            switchActionOnLockHome();
4
419
            //TODO dodać wylaczanie wiatraka
4
420
        }
12
421
        else if (my_data->main_iDomStatus->getObjectState("music") == STATE::STOP)
4
422
        {
4
423
            MPD_play(my_data);
4
424
            switchActionOnUnlockHome();
4
425
            if(isItDay() == false)
4
426
            {
4
427
                ledOn(my_data->ptr_pilot_led->colorLED[2]);
4
428
            }
4
429
            radioButton->setState(STATE::PLAY);
4
430
        }
24
431
    }
40
432
    else
16
433
    {
16
434
        ++counter;
16
435
        if (counter == 2)
8
436
        {
8
437
            buttonLockHome();
8
438
            puts("\nzablokuje dom\n");
8
439
            radioButton->setState(STATE::LOCK);
8
440
        }
16
441
        //#ifdef BT_TEST
16
442
        std::cout << "LOCKER TEST iDomTOOLS::button433mhzLockerPressed()- counter: "<<counter <<std::endl;
16
443
        //#endif
16
444
    }
40
445
40
446
}
447
448
void iDomTOOLS::buttonLockHome()
8
449
{
8
450
    ledOFF();
8
451
    MPD_stop();
8
452
    turnOffPrinter();
8
453
    lockHome();
8
454
}
455
456
void iDomTOOLS::buttonUnlockHome()
8
457
{
8
458
    unlockHome();
8
459
    MPD_play(my_data);
8
460
    if(isItDay() == false){
8
461
        ledOn(my_data->ptr_pilot_led->colorLED[2]);
8
462
    }
8
463
}
464
465
bool iDomTOOLS::isItDay()
60
466
{
60
467
    Clock now = Clock::getTime();
60
468
    if(now < iDomTOOLS::getSunriseClock() || now > iDomTOOLS::getSunsetClock()){
56
469
        return false;
56
470
    }
4
471
    return true;
60
472
}
473
474
std::string iDomTOOLS::getAllDataSunrisesunset()
4
475
{
4
476
    return sun.getAllData();
4
477
}
478
479
CARDINAL_DIRECTIONS::ALARM_INFO iDomTOOLS::getLightningStruct()
16
480
{
16
481
    std::lock_guard<std::mutex> lock(m_lightningMutex);
16
482
    return m_lightningStruct;
16
483
}
484
485
void iDomTOOLS::setLightningStruct(CARDINAL_DIRECTIONS::ALARM_INFO &s)
8
486
{
8
487
    std::lock_guard<std::mutex> lock(m_lightningMutex);
8
488
    //std::cout <<"struktura setowana " << s.data.str() <<std::endl;
8
489
    m_lightningStruct = s;
8
490
8
491
    //std::cout <<"struktura już po setowaniu " << m_lightningStruct.data.str() <<std::endl;
8
492
}
493
494
void iDomTOOLS::checkLightning()
4
495
{
4
496
    nlohmann::json jj = useful_F_libs::getJson(my_data->server_settings->lightningApiURL);
4
497
4
498
    CARDINAL_DIRECTIONS::ALARM_INFO lightningData = lightning.lightningAlert(jj);
4
499
    setLightningStruct(lightningData);
4
500
    bool result = lightning.checkLightningAlert(&lightningData);
4
501
4
502
    if(result == true)
4
503
    {
4
504
4
505
        m_viber.setAvatar("http://cyniu88.no-ip.pl/avatar/lightning.jpg");
4
506
        STATE stateMSG = sendViberMsgBool("UWAGA BURZA KOŁO KRAKOWA! "+EMOJI::emoji(E_emoji::THUNDER_CLOUD_AND_RAIN)
4
507
                                          +"\\n\\n "+lightningData.data.str() ,
4
508
                                          my_data->server_settings->viberReceiver.at(0),
4
509
                                          my_data->server_settings->viberSender);
4
510
4
511
        stateMSG = sendViberMsgBool("UWAGA BURZA KOŁO KRAKOWA! "+EMOJI::emoji(E_emoji::THUNDER_CLOUD_AND_RAIN)
4
512
                                    +"\\n\\n "+lightningData.data.str() ,
4
513
                                    my_data->server_settings->viberReceiver.at(1),
4
514
                                    my_data->server_settings->viberSender);
4
515
4
516
        m_viber.setAvatar(my_data->server_settings->viberAvatar);
4
517
        if(stateMSG == STATE::SEND_OK)
0
518
        {
0
519
            log_file_mutex.mutex_lock();
0
520
            log_file_cout << INFO << "wysłano informacje o burzy"<< std::endl;
0
521
            log_file_mutex.mutex_unlock();
0
522
        }
4
523
        else
4
524
        {
4
525
            log_file_mutex.mutex_lock();
4
526
            log_file_cout << ERROR << "nie wysłano informacje o burzy"<< std::endl;
4
527
            log_file_mutex.mutex_unlock();
4
528
        }
4
529
    }
4
530
}
531
532
std::string iDomTOOLS::getSunrise(bool extend )
28
533
{
28
534
    Clock tt = sun.getSunRise();
28
535
    if (extend == true){
12
536
        return "Sunrise time: "+tt.getString();
12
537
    }
16
538
    return tt.getString();
28
539
}
540
541
std::string iDomTOOLS::getSunset(bool extend )
28
542
{
28
543
    Clock tt = sun.getSunSet();
28
544
    if (extend == true){
12
545
        return "Sunset time: "+tt.getString();
12
546
    }
16
547
    return tt.getString();
28
548
}
549
550
Clock iDomTOOLS::getSunsetClock()
10
551
{
10
552
    return sun.getSunSet();
10
553
}
554
555
Clock iDomTOOLS::getSunriseClock()
60
556
{
60
557
    return sun.getSunRise();
60
558
}
559
560
std::string iDomTOOLS::getDayLenght(bool extend )
28
561
{
28
562
    Clock tt = sun.getDayLength();
28
563
    if (extend == true){
12
564
        return "Day Lenght : "+tt.getString();
12
565
    }
16
566
    return tt.getString();
28
567
}
568
569
std::string iDomTOOLS::getWeatherEvent(const std::string& city, unsigned int radius)
4
570
{
4
571
    std::string url = "http://burze.dzis.net/ramka.php?miejscowosc=";
4
572
    url.append(city);
4
573
    url.append("&promien=");
4
574
    url.append(std::to_string(radius));
4
575
    return useful_F_libs::httpPost(url, 10);
4
576
}
577
578
std::vector<WEATHER_ALER> iDomTOOLS::getAlert(std::string data)
4
579
{
4
580
    std::vector<WEATHER_ALER> wAlert;
4
581
    WEATHER_ALER tempWA;
4
582
    std::string d = useful_F_libs::removeHtmlTag(data);
4
583
    std::vector<std::string> vect;
4
584
4
585
    vect = useful_F::split(d,'\n');
4
586
    vect.pop_back();
4
587
    for (auto n : vect)
28
588
    {
28
589
        if (n.find("brak") == std::string::npos)
4
590
        {
4
591
            tempWA.alert = n;
4
592
            tempWA.name = n;
4
593
            tempWA.sended = false;
4
594
            wAlert.push_back(tempWA);
4
595
        }
28
596
    }
4
597
    return {wAlert};
4
598
}
599
600
void iDomTOOLS::textToSpeach(std::vector<std::string> *textVector)
16
601
{
16
602
    if (textVector->empty() ){
4
603
        return;
4
604
    }
12
605
    std::string txt;
12
606
28
607
    for (auto a : *textVector){
28
608
        txt += a;
28
609
    }
12
610
    /////////// start thread TTS - python use ////////////////////////
12
611
    std::string command = " python /home/pi/programowanie/iDom_server_OOP/script/PYTHON/gadacz.py \\"+ txt +"\\";
12
612
    if(my_data->ptr_MPD_info->isPlay){
4
613
4
614
    }
8
615
    else {
8
616
        turnOnSpeakers();
8
617
    }
12
618
#ifndef BT_TEST
619
    system(command.c_str());
620
#endif
12
621
    if(my_data->ptr_MPD_info->isPlay){
4
622
4
623
    }
8
624
    else {
8
625
        turnOffSpeakers();
8
626
    }
12
627
}
628
629
std::string iDomTOOLS::getTextToSpeach()
12
630
{
12
631
    std::vector<std::string> dayL = useful_F::split(getDayLenght(),':');
12
632
    std::stringstream text;
12
633
    std::string smogText = getSmog();
12
634
    int smogInt = std::stoi(smogText);
12
635
    text << "Godzina: " << Clock::getTime().getString();
12
636
    text << ". \nWschód słońca: " << getSunrise();
12
637
    text << ". \nZachód słońca: " << getSunset();
12
638
    text << ". \nDługość dnia: " << dayL[0] << " godzin " << dayL[1] << " minut";
12
639
    text <<". \n";
12
640
    dayL = getTemperature();
12
641
    text << "Temperatura na zewnątrz: " << dayL[1] << " stopnia. \n";
12
642
    text << "Temperatura w pokoju: " << dayL[0] << " stopnia. \n";
12
643
    text << "Smog: " << smogText << " mg/m^3. \n";
12
644
    if (smogInt > 50){
0
645
        int result = smogInt *2;
0
646
        text << "UWAGA! Maksymalna wartość przekroczona " << result << "%.";
0
647
    }
12
648
    return text.str();
12
649
}
650
651
std::vector<std::string> iDomTOOLS::getTemperature()
68
652
{
68
653
    std::vector<std::string> vect = useful_F::split(useful_F::send_to_arduino(my_data,"temperature:22;"),':');
68
654
    return vect;
68
655
}
656
657
std::string iDomTOOLS::getTemperatureString()
8
658
{
8
659
    return useful_F::send_to_arduino(my_data,"temperature:22;");
8
660
}
661
662
std::string iDomTOOLS::getSmog()
52
663
{
52
664
    CURL *curl;
52
665
    CURLcode res;
52
666
    std::string readBuffer;
52
667
    curl = curl_easy_init();
52
668
52
669
    if(curl) {
52
670
        curl_easy_setopt(curl, CURLOPT_URL, "www.smog.krakow.pl");
52
671
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, useful_F_libs::WriteCallback);
52
672
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
52
673
        res = curl_easy_perform(curl);
52
674
        /* Check for errors */
52
675
        if(res != CURLE_OK)
0
676
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
0
677
                    curl_easy_strerror(res));
52
678
52
679
        /* always cleanup */
52
680
        curl_easy_cleanup(curl);
52
681
    }
52
682
    curl_global_cleanup();
52
683
    int start = readBuffer.find("<h2 class=\"polution\">");
52
684
    try {
52
685
        readBuffer = readBuffer.substr(start, 40);
52
686
    }
0
687
    catch (...){
0
688
        log_file_mutex.mutex_lock();
0
689
        log_file_cout << CRITICAL << "wyjatek substr() e getSmog() !!!!!!"<< std::endl;
0
690
        log_file_mutex.mutex_unlock();
0
691
    }
52
692
52
693
    readBuffer = useful_F_libs::find_tag(readBuffer);
52
694
52
695
    return readBuffer;
52
696
}
697
698
void iDomTOOLS::send_temperature_thingSpeak()
28
699
{
28
700
    std::vector<std::string> _temperature = getTemperature();
28
701
    std::string addres = "api.thingspeak.com/update?key=";
28
702
    addres+=key;
28
703
    addres+="&field1=";
28
704
    addres+= _temperature.at(0);
28
705
    // addres.erase(addres.size()-2,addres.size());
28
706
    addres+= "&field3="+_temperature.at(1);
28
707
    addres+="&field2="+getSmog();
28
708
    //////////////////////////////// pozyskanie temperatury
28
709
    allThermometer.updateAll(&_temperature);
28
710
    sendSMSifTempChanged("outside",0);
28
711
    sendSMSifTempChanged("inside",24);
28
712
    std::string s = useful_F_libs::httpPost(addres,10);
28
713
28
714
    if(s == "0"){
0
715
        log_file_mutex.mutex_lock();
0
716
        log_file_cout << CRITICAL << " błąd wysyłania temoeratury na thingspeak: "<< s << std::endl;
0
717
        log_file_mutex.mutex_unlock();
0
718
    }
28
719
}
720
721
void iDomTOOLS::cameraLedON(const std::string& link)
12
722
{
12
723
    Clock t = Clock::getTime();
12
724
    SunRiseSet sun;
12
725
    Clock sunRise, sunSet;
12
726
    sunRise = sun.getSunRise();
12
727
    sunSet = sun.getSunSet();
12
728
    sunSet += Clock(23,30); // +23:30 == -00:30
12
729
    if (t <= sunRise || t >= sunSet){
8
730
        //printf("zapalam leda!\n");
8
731
        std::string s = useful_F_libs::httpPost(link,10);
8
732
        if (s == "ok.\n"){
8
733
            my_data->main_iDomStatus->setObjectState("cameraLED",STATE::ON);
8
734
            // printf("w ifie\n");
8
735
        }
8
736
    }
12
737
    // printf("nie odpalam leda!\n");
12
738
}
739
740
void iDomTOOLS::cameraLedOFF(const std::string& link)
12
741
{
12
742
    std::string s = useful_F_libs::httpPost(link,10);
12
743
    //printf (" camera response '%s' \n", s.c_str());
12
744
    if (s == "ok.\n"){
12
745
        my_data->main_iDomStatus->setObjectState("cameraLED",STATE::OFF);
12
746
        //printf("w ifie\n");
12
747
    }
12
748
}
749
750
nlohmann::json iDomTOOLS::sendViberMsg(const std::string &msg,
751
                                       const std::string &receiver,
752
                                       const std::string &senderName,
753
                                       const std::string& accessToken,
754
                                       const std::string& url)
44
755
{
44
756
    nlohmann::json jj;
44
757
    std::lock_guard<std::mutex> lock(m_msgMutex);
44
758
    jj = nlohmann::json::parse( m_viber.sendViberMSG(msg,receiver,senderName,accessToken,url));
44
759
    return jj;
44
760
}
761
762
nlohmann::json iDomTOOLS::sendViberPicture(const std::string &msg,
763
                                           const std::string &image,
764
                                           const std::string &receiver,
765
                                           const std::string &senderName,
766
                                           const std::string& accessToken,
767
                                           const std::string& url)
100
768
{
100
769
    nlohmann::json jj;
100
770
    std::lock_guard<std::mutex> lock(m_msgMutex);
100
771
    jj = nlohmann::json::parse(m_viber.sendViberPicture(msg,image,receiver,senderName,accessToken,url));
100
772
    return jj;
100
773
}
774
775
STATE iDomTOOLS::sendViberMsgBool(const std::string &msg,
776
                                  const std::string &receiver,
777
                                  const std::string &senderName,
778
                                  const std::string& accessToken,
779
                                  const std::string& url)
8
780
{
8
781
    nlohmann::json jj = sendViberMsg(msg,receiver,senderName,accessToken,url);
8
782
    STATE ret = STATE::SEND_NOK;
8
783
    if(jj.find("status_message")!= jj.end())
0
784
    {
0
785
        if(jj.at("status_message").get<std::string>() == "ok")
0
786
        {
0
787
            ret = STATE::SEND_OK;
0
788
        }
0
789
    }
8
790
    else
8
791
    {
8
792
        log_file_mutex.mutex_lock();
8
793
        log_file_cout << ERROR << "nie wyslanno wiadomosci viber"<< jj.dump()<< std::endl;
8
794
        log_file_mutex.mutex_unlock();
8
795
    }
8
796
    return ret;
8
797
}
798
799
STATE iDomTOOLS::sendViberPictureBool(const std::string& msg,
800
                                      const std::string& image,
801
                                      const std::string& receiver,
802
                                      const std::string& senderName,
803
                                      const std::string& accessToken,
804
                                      const std::string& url)
0
805
{
0
806
    nlohmann::json jj = sendViberPicture(msg,image,receiver,senderName,accessToken,url);
0
807
    STATE ret = STATE::SEND_NOK;
0
808
    if(jj.at("status_message").get<std::string>() == "ok")
0
809
    {
0
810
        ret = STATE::SEND_OK;
0
811
    }
0
812
    else
0
813
    {
0
814
        log_file_mutex.mutex_lock();
0
815
        log_file_cout << ERROR << "nie wyslanno wiadomosci viber"<< jj.dump()<< std::endl;
0
816
        log_file_mutex.mutex_unlock();
0
817
    }
0
818
    return ret;
0
819
}
820
821
std::string iDomTOOLS::postOnFacebook(const std::string& msg, const std::string& image)
8
822
{
8
823
    std::lock_guard<std::mutex> lock(m_msgMutex);
8
824
    if (image != "NULL"){
8
825
        return m_facebook.postPhotoOnWall(image,msg);
8
826
    }
8
827
0
828
    return m_facebook.postTxtOnWall(msg);
8
829
}
830
831
std::string iDomTOOLS::ledOFF()
40
832
{
40
833
    return useful_F::send_to_arduino(my_data,"LED_STOP:2;");
40
834
}
835
836
std::string iDomTOOLS::ledClear()
4
837
{
4
838
    return useful_F::send_to_arduino(my_data,"LED_CLEAR:2;");
4
839
}
840
841
std::string iDomTOOLS::ledClear(unsigned int from, unsigned int to)
44
842
{
44
843
    LED_Strip ledColor(0,60,0,0,0,"BLACK");
44
844
    useful_F::send_to_arduino(my_data,ledColor.get(from, to));
44
845
    return "Led cleared";
44
846
}
847
848
std::string iDomTOOLS::ledOn(const LED_Strip& ledColor, unsigned int from, unsigned int to)
84
849
{
84
850
    if (my_data->idom_all_state.houseState == STATE::UNLOCK)
12
851
    {
12
852
        return useful_F::send_to_arduino(my_data,ledColor.get(from, to));
12
853
    }
72
854
    else{
72
855
        my_data->myEventHandler.run("LED")->addEvent("LED can not start due to home state: "+
72
856
                                                     stateToString(my_data->idom_all_state.houseState));
72
857
    }
72
858
    return "iDom LOCKED!";
84
859
}
860
861
void iDomTOOLS::checkAlarm()
40
862
{
40
863
    unsigned int fromVol = my_data->alarmTime.fromVolume;
40
864
    unsigned int toVol   = my_data->alarmTime.toVolume;
40
865
    unsigned int radioId = my_data->alarmTime.radioID;
40
866
40
867
    Clock now = Clock::getTime();
40
868
    if (now == my_data->alarmTime.time && my_data->alarmTime.state == STATE::ACTIVE){
4
869
        my_data->alarmTime.state = STATE::WORKING;
4
870
        MPD_volumeSet(my_data, fromVol);
4
871
        MPD_play(my_data,radioId);
4
872
        my_data->main_iDomStatus->setObjectState("alarm",STATE::DEACTIVE);
4
873
    }
40
874
40
875
    if (my_data->alarmTime.state == STATE::WORKING){
40
876
        unsigned int vol = MPD_getVolume(my_data) + 1;
40
877
        if (vol < toVol){
36
878
            MPD_volumeSet(my_data, vol);
36
879
36
880
            if(iDomTOOLS::isItDay() == false){
36
881
                my_data->main_iDomTools->ledOn(my_data->ptr_pilot_led->colorLED[2],fromVol,vol);
36
882
            }
36
883
        }
4
884
        else{
4
885
            my_data->alarmTime.state = STATE::DEACTIVE;
4
886
            if(iDomTOOLS::isItDay() == false){
4
887
                // my_data->main_iDomTools->turnOn433MHzSwitch("ALARM");
4
888
            }
4
889
        }
40
890
    }
40
891
}
892
893
void iDomTOOLS::saveState_iDom()
164
894
{
164
895
    iDom_SAVE_STATE info(my_data->server_settings->saveFilePath);
164
896
    nlohmann::json jsonAlarm;
164
897
    nlohmann::json jsonMPD;
164
898
    nlohmann::json json_iDomLOCK;
164
899
    nlohmann::json json433Mhz;
164
900
    //////////////////// iDom
164
901
    json_iDomLOCK["iDomLock"] = stateToString(my_data->idom_all_state.houseState);
164
902
    //////////////////// alarm
164
903
    jsonAlarm["alarm"] = my_data->main_iDomStatus->getObjectStateString("alarm");
164
904
    jsonAlarm["time"]  = my_data->alarmTime.time.getString();
164
905
    jsonAlarm["fromVolume"] = my_data->alarmTime.fromVolume;
164
906
    jsonAlarm["toVolume"] = my_data->alarmTime.toVolume;
164
907
    jsonAlarm["radioID"] = my_data->alarmTime.radioID;
164
908
    //////////////////// mpd
164
909
    jsonMPD["music"] = my_data->main_iDomStatus->getObjectStateString("music");
164
910
    jsonMPD["speakers"] = my_data->main_iDomStatus->getObjectStateString("speakers");
164
911
    ////////////////// 433Mhz
164
912
    auto switch433vector = my_data->main_REC->getSwitchPointerVector();
164
913
    for (auto v : switch433vector)
820
914
    {
820
915
        v->getName();
820
916
        json433Mhz[v->getName()] = stateToString(v->getState());
820
917
    }
164
918
    ///
164
919
    nlohmann::json json;
164
920
    json["iDom"] = json_iDomLOCK;
164
921
    json["ALARM"] = jsonAlarm;
164
922
    json["MPD"] = jsonMPD;
164
923
    json["433Mhz"] = json433Mhz;
164
924
164
925
    info.write(json);
164
926
#ifdef BT_TEST
164
927
    std::cout << json <<std::endl;
164
928
    std::cout << " saved to " << my_data->server_settings->saveFilePath <<std::endl;
164
929
#endif
164
930
}
931
932
void iDomTOOLS::readState_iDom()
4
933
{
4
934
    try
4
935
    {
4
936
        iDom_SAVE_STATE info(my_data->server_settings->saveFilePath);
4
937
        nlohmann::json jj = info.read();
4
938
#ifdef BT_TEST
4
939
        std::cout << "JSON: " << jj.dump(4) << std::endl;
4
940
#endif
4
941
        nlohmann::json json433MHz = jj.at("433Mhz");
4
942
24
943
        for (nlohmann::json::iterator it = json433MHz.begin(); it != json433MHz.end(); ++it)
20
944
        {
20
945
            if( it.value() == "ON"){
0
946
                my_data->main_iDomTools->turnOn433MHzSwitch(it.key());
0
947
            }
20
948
            else if ( it.value() == "OFF"){
0
949
                my_data->main_iDomTools->turnOff433MHzSwitch(it.key());
0
950
            }
20
951
        }
4
952
        auto iDomLock = jj.at("iDom").at("iDomLock").get<std::string>();
4
953
4
954
        if(iDomLock == "UNLOCK")
0
955
            unlockHome();
4
956
        else if (iDomLock == "LOCK")
4
957
            lockHome();
4
958
4
959
        auto mpdMusic = jj.at("MPD").at("music").get<std::string>();
4
960
        auto mpdSpeakers = jj.at("MPD").at("speakers").get<std::string>();
4
961
4
962
        if(mpdMusic == "PLAY")
4
963
            MPD_play(my_data);
0
964
        else if(mpdMusic == "STOP")
0
965
            MPD_stop();
4
966
        if(mpdSpeakers == "ON")
4
967
            turnOnSpeakers();
0
968
        else if(mpdSpeakers == "OFF")
0
969
            turnOffSpeakers();
4
970
4
971
        auto alarmState = jj.at("ALARM").at("alarm").get<std::string>();
4
972
        auto alarmTime  = jj.at("ALARM").at("time").get<std::string>();
4
973
        my_data->alarmTime.fromVolume = jj.at("ALARM").at("fromVolume").get<int>();
4
974
        my_data->alarmTime.toVolume = jj.at("ALARM").at("toVolume").get<int>();
4
975
        my_data->alarmTime.radioID = jj.at("ALARM").at("radioID").get<int>();
4
976
        my_data->alarmTime.time = Clock(alarmTime);
4
977
4
978
        if (alarmState == "ACTIVE"){
4
979
            my_data->alarmTime.state = STATE::ACTIVE;
4
980
            my_data->main_iDomStatus->setObjectState("alarm", my_data->alarmTime.state);
4
981
            saveState_iDom();
4
982
        }
4
983
    }
4
984
    catch(...)
0
985
    {
0
986
        log_file_mutex.mutex_lock();
0
987
        log_file_cout << ERROR << "nie ma pliku json z stanem iDom"<< std::endl;
0
988
        log_file_mutex.mutex_unlock();
0
989
#ifdef BT_TEST
0
990
        std::cout << "nie ma pliku json z stanem iDom" << std::endl;
0
991
#endif
0
992
    }
4
993
}
994
995
std::string iDomTOOLS::startKodi_Thread()
16
996
{
16
997
    STATE kodiState = my_data->main_iDomStatus->getObjectState("KODI");
16
998
    if (kodiState == STATE::ACTIVE)
4
999
        return "kodi already run";
16
1000
12
1001
    return iDOM_THREAD::start_thread("kodi smartTV",useful_F::kodi,my_data);
16
1002
}
/home/pi/programowanie/iDom_server_OOP/src/iDomTools/idomtools_mpd.cpp
1
#include "idomtools.h"
2
#include "../blockQueue/blockqueue.h"
3
#include "../functions/functions.h"
4
5
void iDomTOOLS::MPD_play(thread_data* my_data)
40
6
{
40
7
    if(my_data->idom_all_state.houseState == STATE::UNLOCK)
20
8
    {
20
9
        blockQueue _q;
20
10
        _q._add(MPD_COMMAND::PLAY);
20
11
    }
40
12
    else
20
13
    {
20
14
        my_data->myEventHandler.run("MPD")->addEvent("MPD can not start due to home state: "+
20
15
                                                     stateToString(my_data->idom_all_state.houseState));
20
16
    }
40
17
}
18
19
void iDomTOOLS::MPD_stop()
32
20
{
32
21
    blockQueue _q;
32
22
    _q._add(MPD_COMMAND::STOP);
32
23
}
24
25
void iDomTOOLS::MPD_next()
4
26
{
4
27
    blockQueue _q;
4
28
    _q._add(MPD_COMMAND::NEXT);
4
29
}
30
31
void iDomTOOLS::MPD_prev()
4
32
{
4
33
    blockQueue _q;
4
34
    _q._add(MPD_COMMAND::PREV);
4
35
}
36
37
void iDomTOOLS::MPD_pause()
16
38
{
16
39
    blockQueue _q;
16
40
    _q._add(MPD_COMMAND::PAUSE);
16
41
}
42
43
void iDomTOOLS::MPD_volumeUp()
4
44
{
4
45
    blockQueue _q;
4
46
    _q._add(MPD_COMMAND::VOLUP);
4
47
}
48
49
void iDomTOOLS::MPD_volumeDown()
4
50
{
4
51
    blockQueue _q;
4
52
    _q._add(MPD_COMMAND::VOLDOWN);
4
53
}
54
55
void iDomTOOLS::MPD_volumeSet(thread_data *my_data, int vol)
44
56
{
44
57
    my_data->ptr_MPD_info->volume = vol;
44
58
    blockQueue _q;
44
59
    _q._add(MPD_COMMAND::VOLSET);
44
60
}
61
62
void iDomTOOLS::MPD_play(thread_data *my_data, int id)
12
63
{
12
64
    if(my_data->idom_all_state.houseState == STATE::UNLOCK)
4
65
    {
4
66
        my_data->ptr_MPD_info->currentSongID = id;
4
67
        blockQueue _q;
4
68
        _q._add(MPD_COMMAND::PLAY_ID);
4
69
    }
12
70
    else
8
71
    {
8
72
        my_data->myEventHandler.run("MPD")->addEvent("MPD can not start due to home state: "+
8
73
                                                     stateToString(my_data->idom_all_state.houseState));
8
74
    }
12
75
}
76
77
int iDomTOOLS::MPD_getVolume(thread_data *my_data)
44
78
{
44
79
    return my_data->ptr_MPD_info->volume;
44
80
}
/home/pi/programowanie/iDom_server_OOP/src/iDomTools/idomtools_system.cpp
1
#include "idomtools.h"
2
#include <sys/sysinfo.h>
3
#include <sys/utsname.h>
4
#include <sys/resource.h>
5
#include <sys/time.h>
6
#include <unistd.h>
7
8
std::string iDomTOOLS::getSystemInfo()
8
9
{
8
10
    double load[3];
8
11
    if (getloadavg(load, 3) != -1)
8
12
    {
8
13
#ifdef BT_TEST
8
14
        printf("load average : %f , %f , %f\n", load[0],load[1],load[2]);
8
15
#endif
8
16
    }
8
17
    const double megabyte = 1024 * 1024;
8
18
    struct sysinfo info;
8
19
    sysinfo(&info);
8
20
8
21
    long input_seconds = info.uptime;
8
22
    auto days = input_seconds / 60 / 60 / 24;
8
23
    auto hours = (input_seconds / 60 / 60) % 24;
8
24
    auto minutes = (input_seconds / 60) % 60;
8
25
    auto seconds = input_seconds % 60;
8
26
8
27
    std::stringstream ret;
8
28
    ret << "System uptime: " << days <<" day " << hours
8
29
        << " hours " << minutes << " minutes "
8
30
        << seconds << " seconds " << std::endl << "Load: "
8
31
        << (info.loads[0]/65536) << "% - 1 min, " <<(info.loads[1]/65536)
8
32
        << "% - 5 min, "<<(info.loads[2]/65536) << "% - 15 min." << std::endl
8
33
        << "process count : " << info.procs << std::endl
8
34
        << "total RAM   : "<< (info.totalram / megabyte)<< "MB" << std::endl
8
35
        << "free RAM   : " << (info.freeram / megabyte) << "MB" << std::endl;
8
36
8
37
    return ret.str();
8
38
}
39
/home/pi/programowanie/iDom_server_OOP/src/iDomTools/lightning.cpp
1
#include "lightning.h"
2
3
LIGHTNING::LIGHTNING()
1.07k
4
{
1.07k
5
    puts("LIGHTNING::LIGHTNING()");
1.07k
6
}
7
8
LIGHTNING::~LIGHTNING()
1.07k
9
{
1.07k
10
    puts("LIGHTNING::~LIGHTNING()");
1.07k
11
}
12
13
CARDINAL_DIRECTIONS::ALARM_INFO LIGHTNING::lightningAlert(nlohmann::json jj)
52
14
{
52
15
    CARDINAL_DIRECTIONS::ALARM_INFO data;
52
16
    nlohmann::json i;
52
17
52
18
#ifdef BT_TEST
52
19
    std::cout <<"\n\n data all " << i.dump(4) <<" size:"<< i.size() <<std::endl;
52
20
#endif
52
21
    if (jj.find("response") != jj.end())
48
22
    {
48
23
        i = jj.at("response").get<nlohmann::json>();
48
24
    }
52
25
    else
4
26
    {
4
27
        std::cout << " zly JSON " <<std::endl;
4
28
        return data;
4
29
    }
52
30
48
31
    auto _size = i.size();
48
32
    if (_size == 0)
16
33
    {
16
34
        data.riseAlarm = false;
16
35
        return data;
16
36
    }
32
37
    STATISTIC<int> ageAver(_size);
32
38
    STATISTIC<double> distanceKmAver(_size);
32
39
    STATISTIC<int> bearingAver(_size);
584
40
    for (auto j : i){
584
41
#ifdef BT_TEST
584
42
   //     std::cout <<"\n distance " << j.at("relativeTo").at("bearingENG").get<std::string>() << std::endl;
584
43
   //     std::cout <<"distance " << j.at("relativeTo").at("distanceKM").get<double>() << std::endl;
584
44
   //     std::cout <<"timestamp " << j.at("age").get<int>() << std::endl;
584
45
#endif
584
46
        ageAver.push_back(j.at("age").get<int>());
584
47
        distanceKmAver.push_back(j.at("relativeTo").at("distanceKM").get<double>());
584
48
        bearingAver.push_back(static_cast<int>(CARDINAL_DIRECTIONS::stringToCardinalDirectionsEnum(
584
49
                                                   j.at("relativeTo").at("bearingENG").get<std::string>()))
584
50
                              );
584
51
    }
32
52
    data.bearingENG = static_cast<CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM>(bearingAver.mode());
32
53
    data.distance = distanceKmAver.average();
32
54
    data.timestamp = ageAver.median();
32
55
32
56
    data.data.str(std::string());
32
57
    data.data << "ilość uderzeń: "<< _size << "\\n";
32
58
    data.data << "średni czas upłynięty od ostatniego uderzenia pioruna: "<< data.timestamp << " sek \\n";
32
59
    data.data << "średnia odległość ostatniego uderzenia pieruna: "<< data.distance <<" km \\n ";
32
60
    data.data << "kierunek uderzeń piorunów: " << CARDINAL_DIRECTIONS::cardinalDirectionsEnumToHuman(data.bearingENG);
32
61
32
62
    if(i.size() > 0){
32
63
        // std::cout << "jest size: " << i.size()<<std::endl;
32
64
        data.riseAlarm = true;
32
65
    }
32
66
32
67
    return data;
48
68
}
69
70
bool LIGHTNING::checkLightningAlert(CARDINAL_DIRECTIONS::ALARM_INFO *info)
60
71
{
60
72
#ifdef BT_TEST
60
73
    std::cout << "LIGHTNING::checkLightningAlert() bool "<< info->riseAlarm <<" local " << alarmState << std::endl
60
74
              << " distance " << info->distance << std::endl;
60
75
#endif
60
76
    if(info->riseAlarm == false && alarmState == false){
16
77
#ifdef BT_TEST
16
78
        std::cout << "(info->riseAlarm == false || alarmState == false)"<<std::endl;
16
79
#endif
16
80
        return false;
16
81
    }
44
82
    if(info->riseAlarm == false && alarmState == true){
8
83
#ifdef BT_TEST
8
84
        std::cout << "(info->riseAlarm == false || alarmState == true)"<<std::endl;
8
85
#endif
8
86
        alarmState = false;
8
87
        return false;
8
88
    }
36
89
    if(info->riseAlarm == true && alarmState == false){
20
90
20
91
#ifdef BT_TEST
20
92
        std::cout << "(info->riseAlarm == true || alarmState == false)"<<std::endl;
20
93
#endif
20
94
        alarmState = true;
20
95
        lightningTime = Clock::getTime();
20
96
        oldDistance = info->distance;
20
97
        std::cout << " w true oldDistance: "<< oldDistance <<std::endl;
20
98
        return true;
20
99
    }
36
100
36
101
#ifdef BT_TEST
16
102
    std::cout << "checkLightningAlert() - dystans"<<std::endl;
16
103
    std::cout << "Dystans: " <<info->distance << " oldDistance: "<< oldDistance <<std::endl;
16
104
#endif
16
105
    if(oldDistance > info->distance)
4
106
    {
4
107
4
108
        oldDistance = info->distance;
4
109
        return true;
4
110
    }
16
111
    else
12
112
    {
12
113
        oldDistance = info->distance;
12
114
    }
16
115
    ////////////////clear
16
116
    //oldDistance = 0.0;
12
117
    return false;
16
118
}
119
/home/pi/programowanie/iDom_server_OOP/src/iDomTools/lightning.h
1
#ifndef LIGHTNING_H
2
#define LIGHTNING_H
3
#include <iostream>
4
5
#include "../../libs/Statistic/statistic.h"
6
#include "../../libs/useful/useful.h"
7
8
#include "idomtools_useful.h"
9
#include "json.hpp"
10
11
class CARDINAL_DIRECTIONS{
12
public:
13
    enum class CARDINAL_DIRECTIONS_ENUM{
14
        /*
15
           N
16
        NNW NNE
17
      NW       NE
18
   WNW		     ENE
19
 W				    E
20
   WSW			 ESE
21
      SW	   SE
22
        SSW	 SSE
23
           S
24
    */
25
26
        N = 1,NNE,NE,ENE,E,ESE,SE,SSE,S,SSW,SW,WSW,W,WNW,NW,NNW,ERROR
27
    };
28
    static CARDINAL_DIRECTIONS_ENUM stringToCardinalDirectionsEnum(std::string s){
29
        if (s == "N")      return CARDINAL_DIRECTIONS_ENUM::N;
30
        else if (s == "NNE")    return CARDINAL_DIRECTIONS_ENUM::NNE;
31
        else if (s == "NE")     return CARDINAL_DIRECTIONS_ENUM::NE;
32
        else if (s == "ENE")    return CARDINAL_DIRECTIONS_ENUM::ENE;
33
        else if (s == "E")      return CARDINAL_DIRECTIONS_ENUM::E;
34
        else if (s == "ESE")    return CARDINAL_DIRECTIONS_ENUM::ESE;
35
        else if (s == "SE")     return CARDINAL_DIRECTIONS_ENUM::SE;
36
        else if (s == "SSE")    return CARDINAL_DIRECTIONS_ENUM::SSE;
37
        else if (s == "S")      return CARDINAL_DIRECTIONS_ENUM::S;
38
        else if (s == "SSW")    return CARDINAL_DIRECTIONS_ENUM::SSW;
39
        else if (s == "SW")     return CARDINAL_DIRECTIONS_ENUM::SW;
40
        else if (s == "WSW")    return CARDINAL_DIRECTIONS_ENUM::WSW;
41
        else if (s == "W")      return CARDINAL_DIRECTIONS_ENUM::W;
42
        else if (s == "WNW")    return CARDINAL_DIRECTIONS_ENUM::WNW;
43
        else if (s == "NW")     return CARDINAL_DIRECTIONS_ENUM::NW;
44
        else if (s == "NNW")    return CARDINAL_DIRECTIONS_ENUM::NNW;
45
        else                    return CARDINAL_DIRECTIONS_ENUM::ERROR;
46
    }
47
48
    static std::string cardinalDirectionsEnumToString(CARDINAL_DIRECTIONS_ENUM e){
49
        switch (e){
50
        case CARDINAL_DIRECTIONS_ENUM::N:
51
            return "N";
52
        case CARDINAL_DIRECTIONS_ENUM::NNE:
53
            return "NNE";
54
        case CARDINAL_DIRECTIONS_ENUM:: NE:
55
            return "NE";
56
        case CARDINAL_DIRECTIONS_ENUM::ENE:
57
            return "ENE";
58
        case CARDINAL_DIRECTIONS_ENUM::E:
59
            return "E";
60
        case CARDINAL_DIRECTIONS_ENUM::ESE:
61
            return "ESE";
62
        case CARDINAL_DIRECTIONS_ENUM::SE:
63
            return "SE";
64
        case CARDINAL_DIRECTIONS_ENUM::SSE:
65
            return "SSE";
66
        case CARDINAL_DIRECTIONS_ENUM::S:
67
            return "S";
68
        case CARDINAL_DIRECTIONS_ENUM::SSW:
69
            return "SSW";
70
        case CARDINAL_DIRECTIONS_ENUM::SW:
71
            return "SW";
72
        case CARDINAL_DIRECTIONS_ENUM::WSW:
73
            return "WSW";
74
        case CARDINAL_DIRECTIONS_ENUM::W:
75
            return "W";
76
        case CARDINAL_DIRECTIONS_ENUM::WNW:
77
            return "WNW";
78
        case CARDINAL_DIRECTIONS_ENUM::NW:
79
            return "NW";
80
        case CARDINAL_DIRECTIONS_ENUM::NNW:
81
            return "NNW";
82
        default:
83
            return "UNKNOWN DIRECTION";
84
        }
85
    }
32
86
    static std::string cardinalDirectionsEnumToHuman(CARDINAL_DIRECTIONS_ENUM e){
0
87
        switch (e){
0
88
        case CARDINAL_DIRECTIONS_ENUM::N:
0
89
            return "północ";
0
90
        case CARDINAL_DIRECTIONS_ENUM::NNE:
0
91
            return "północ - północny wschód";
0
92
        case CARDINAL_DIRECTIONS_ENUM:: NE:
0
93
            return "północny wschód";
24
94
        case CARDINAL_DIRECTIONS_ENUM::ENE:
24
95
            return "wschód - północny wschód";
0
96
        case CARDINAL_DIRECTIONS_ENUM::E:
0
97
            return "wschód";
0
98
        case CARDINAL_DIRECTIONS_ENUM::ESE:
0
99
            return "wschód - południowy wschód";
0
100
        case CARDINAL_DIRECTIONS_ENUM::SE:
0
101
            return "południowy wschód";
0
102
        case CARDINAL_DIRECTIONS_ENUM::SSE:
0
103
            return "południe - południowy wschód";
0
104
        case CARDINAL_DIRECTIONS_ENUM::S:
0
105
            return "południe";
0
106
        case CARDINAL_DIRECTIONS_ENUM::SSW:
0
107
            return "południe - południowy zachów";
0
108
        case CARDINAL_DIRECTIONS_ENUM::SW:
0
109
            return "południowy zachów";
8
110
        case CARDINAL_DIRECTIONS_ENUM::WSW:
8
111
            return "zachód - południowy zachów";
0
112
        case CARDINAL_DIRECTIONS_ENUM::W:
0
113
            return "zachód";
0
114
        case CARDINAL_DIRECTIONS_ENUM::WNW:
0
115
            return "zachód - północny zachód";
0
116
        case CARDINAL_DIRECTIONS_ENUM::NW:
0
117
            return "północny zachód";
0
118
        case CARDINAL_DIRECTIONS_ENUM::NNW:
0
119
            return "północ - północny zachód";
0
120
        default:
0
121
            return "UNKNOWN DIRECTION";
0
122
        }
32
123
    }
124
    struct ALARM_INFO{
125
        ALARM_INFO():
126
            riseAlarm(false),
127
            timestamp(0),
128
            distance(0.0),
129
            bearingENG(CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ERROR)
130
        {
131
            data << "NULL";
132
        }
133
        ALARM_INFO(const ALARM_INFO &s):
134
            riseAlarm(s.riseAlarm),
135
            data(s.data.str()),
136
            timestamp(s.timestamp),
137
            distance(s.distance),
138
            bearingENG(s.bearingENG)
16
139
        {
16
140
        }
141
        ALARM_INFO& operator = (const ALARM_INFO& s)
142
        {
143
            this->data.str(std::string());
144
            this->riseAlarm = s.riseAlarm;
145
            this->data << s.data.str();
146
            this->timestamp = s.timestamp;
147
            this->distance = s.distance;
148
            this->bearingENG = s.bearingENG;
149
            return *this;
150
        }
151
152
        bool riseAlarm;
153
        std::stringstream data;
154
        unsigned int timestamp; //second
155
        double distance; //km
156
        CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM bearingENG;
157
    };
158
};
159
160
class LIGHTNING
161
{
162
public:
163
    LIGHTNING();
164
    ~LIGHTNING();
165
    CARDINAL_DIRECTIONS::ALARM_INFO lightningAlert(nlohmann::json jj);
166
    bool checkLightningAlert(CARDINAL_DIRECTIONS::ALARM_INFO* info);
167
private:
168
    bool alarmState = false;
169
    Clock lightningTime;
170
    double oldDistance = 0.0;
171
};
172
173
#endif // LIGHTNING_H
/home/pi/programowanie/iDom_server_OOP/src/iDomTools/test/../../../libs/useful/useful.h
1
#ifndef Iusefull_H
2
#define Iusefull_H
3
4
#include <iostream>
5
#include <string>
6
#include <vector>
7
#include <ostream>
8
#include <chrono>
9
#include <sstream>
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <iomanip>
13
#ifndef ANDROID
14
#include "json.hpp"
15
#endif
16
17
std::vector<std::string> split_string(const std::string& s, char separator );
18
19
class useful_F_libs {
20
public:
21
    static  void write_to_mkfifo(const std::string& path, const std::string &msg);
22
    static  std::string read_from_mkfifo(const std::string &path);
23
    static size_t  WriteCallback(void *contents, size_t size, size_t nmemb, void *userp);
24
    static std::string find_tag (const std::string &temp);
25
    //////////////////// HTTP req //////////////////////////
26
    static std::string httpPost(const std::string &url, int timeoutSeconds);
27
    static std::string httpPost(const std::string &url);
28
    static void downloadFile(const std::string &url, const std::string &path, int timeoutSeconds);
29
    static std::string replaceAll(std::string str, const std::string& from, const std::string& to);
30
    static std::string removeHtmlTag(std::string &data);
31
    /////////////////////  JSON ////////////////////////////
32
33
#ifndef ANDROID
34
    static nlohmann::json getJson(const std::string &url);
35
#endif
36
};
37
namespace std
38
{
39
40
#ifdef ANDROID
41
template <typename T>
42
int stoi(T s){
43
    return atoi(s.c_str());
44
}
45
#endif
46
47
template <typename T>
48
std::string to_string(T value)
8
49
{
8
50
    std::ostringstream os;
8
51
    os << value;
8
52
    return os.str();
8
53
}
54
} // namespace std
55
56
template <typename T>
57
std::string to_string_with_precision(const T a_value, const int n = 4)
58
{
59
    std::ostringstream out;
60
    out << std::setprecision(n) << a_value;
61
    return out.str();
62
}
63
64
struct Clock{
65
private:
66
    std::time_t m_time;
67
#ifdef BT_TEST
68
    static unsigned int m_BT_H;
69
    static unsigned int m_BT_M;
70
#endif
71
public:
72
    unsigned int m_h = 0;
73
    unsigned int m_min = 0;
74
    Clock () {}
75
    Clock(std::string t){
76
        std::vector<std::string> vt = split_string(t,':');
77
        int h = std::stoi(vt.at(0));
78
        int m = std::stoi(vt.at(1));
79
        set(static_cast <unsigned int>(h),static_cast <unsigned int>(m));
80
    }
81
82
    Clock(unsigned int h, unsigned int m) {
83
        set(h,m);
84
    }
85
    /////////////////////////////////////////////////////////////////////////////////////
86
    void set(unsigned int h, unsigned int m){
87
        if (h<24 && m <60){
88
            this->m_h = h;
89
            this->m_min = m;
90
        }
91
        else {
92
            throw 0;
93
        }
94
    }
95
96
    /////////////////////////////////////////////////////////////////////////////////////
97
    const std::string getString(){
98
        std::stringstream ret;
99
        if (m_h < 10) {
100
            ret << "0";
101
        }
102
        ret << m_h;
103
        ret << ":";
104
        if (m_min < 10) {
105
            ret << "0";
106
        }
107
        ret << m_min;
108
        return ret.str();
109
    }
110
    /////////////////////////////////////////////////////////////////////////////////////
111
    bool operator == (const Clock & c){
112
        if ((this->m_h == c.m_h) && (this->m_min == c.m_min)){
113
            return true;
114
        }
115
        else{
116
            return false;
117
        }
118
    }
119
    /////////////////////////////////////////////////////////////////////////////////////
120
    bool operator != (const Clock & c){
121
        if ((this->m_h != c.m_h) || (this->m_min != c.m_min)){
122
            return true;
123
        }
124
        else{
125
            return false;
126
        }
127
    }
128
    /////////////////////////////////////////////////////////////////////////////////////
129
    friend std::ostream & operator<< (std::ostream &w ,  Clock &c) {
130
        return w << c.getString();
131
    }
132
    /////////////////////////////////////////////////////////////////////////////////////
133
    bool operator < (const Clock& c){
134
        if (this->m_h < c.m_h){
135
            return true;
136
        }
137
        else{
138
            if (this->m_h == c.m_h && this->m_min < c.m_min){
139
                return true;
140
            }
141
        }
142
        return false;
143
    }
144
    /////////////////////////////////////////////////////////////////////////////////////
145
    bool operator > (const Clock& c){
146
        if (this->m_h > c.m_h){
147
            return true;
148
        }
149
        else{
150
            if (this->m_h == c.m_h && this->m_min > c.m_min){
151
                return true;
152
            }
153
        }
154
        return false;
155
    }
156
    /////////////////////////////////////////////////////////////////////////////////////
157
    bool operator >= (const Clock& c){
158
        if (this->m_h > c.m_h){
159
            return true;
160
        }
161
        else if (this->m_h == c.m_h){
162
163
            if (this->m_min >= c.m_min){
164
                return true;
165
            }
166
        }
167
        return false;
168
    }
169
    /////////////////////////////////////////////////////////////////////////////////////
170
    bool operator <= (const Clock& c){
171
        if (this->m_h < c.m_h){
172
            return true;
173
        }
174
        else if (this->m_h == c.m_h){
175
176
            if (this->m_min <= c.m_min){
177
                return true;
178
            }
179
        }
180
        return false;
181
    }
182
    /////////////////////////////////////////////////////////////////////////////////////
183
    Clock  operator + (const Clock& c){
184
        unsigned int minutes, hours;
185
        minutes = m_min+ c.m_min;
186
        hours = m_h + c.m_h;
187
        if (minutes >59){
188
            minutes =  minutes % 60;
189
            hours+=1;
190
        }
191
        if (hours >= 24){
192
            hours-=24;
193
        }
194
        return  Clock(hours, minutes);
195
196
    }
197
    /////////////////////////////////////////////////////////////////////////////////////
198
    Clock&  operator += (const Clock& c){
199
        unsigned int minutes, hours;
200
        minutes = m_min+ c.m_min;
201
        hours = m_h + c.m_h;
202
        if (minutes >59){
203
            minutes =  minutes % 60;
204
            hours+=1;
205
        }
206
        if (hours >= 24){
207
            hours-=24;
208
        }
209
        this->m_h = hours;
210
        this->m_min = minutes;
211
        return *this;
212
213
    }
214
    /////////////////////////////////////////////////////////////////////////////////////
215
216
    unsigned int toSeconds(){
217
        return toSeconds(Clock(this->m_h, this->m_min) );
218
    }
219
    /////////////////////////////////////////////////////////////////////////////////////
220
221
    static unsigned int toSeconds(Clock t){
222
        return ((t.m_h*60) + t.m_min)*60;
223
    }
224
    /////////////////////////////////////////////////////////////////////////////////////
225
226
    static Clock fromSeconds(unsigned int sec){
227
        unsigned int h = sec/3600;
228
        unsigned int min = sec%3600;
229
        min = min/60;
230
        return Clock(h,min);
231
    }
232
    /////////////////////////////////////////////////////////////////////////////////////
233
234
    static Clock periodOfTime(Clock start, Clock end)
235
    {
236
        if (end >= start){
237
            return Clock::fromSeconds(end.toSeconds() - start.toSeconds()  );
238
        }
239
        else{
240
            return Clock::fromSeconds(end.toSeconds() + ( Clock::toSeconds(Clock(23,59))+ 60 - start.toSeconds() ) );
241
        }
242
        //return diff;
243
    }
244
    ////////////////////////////////////////////////////////////////////////////////////
245
    static unsigned int getUnixTime()
246
    {
247
        return static_cast<unsigned int> (std::time(nullptr));
248
    }
249
    /////////////////////////////////////////////////////////////////////////////////////
250
#ifdef BT_TEST
251
    static void setTime_forBT_usage(int h, int m)
24
252
    {
24
253
        m_BT_H = h;
24
254
        m_BT_M = m;
24
255
    }
256
#endif
257
    /////////////////////////////////////////////////////////////////////////////////////
258
    static Clock getTime()
259
    {
260
#ifdef BT_TEST
261
        return Clock(m_BT_H,m_BT_M);
262
#else
263
        time_t now = time(0);
264
        tm *ltm = localtime(&now);
265
        return Clock( static_cast <unsigned int>(ltm->tm_hour),static_cast <unsigned int>(ltm->tm_min) );
266
#endif
267
    }
268
    /////////////////////////////////////////////////////////////////////////////////////
269
    void stopwatchStart()
270
    {
271
        m_time = std::time(nullptr);
272
    }
273
    /////////////////////////////////////////////////////////////////////////////////////
274
    unsigned int  stopwatchStopAndGetResult()
275
    {
276
        return static_cast<unsigned int>(std::time(nullptr) - m_time);
277
    }
278
};
279
280
enum class STATE {
281
    OFF,
282
    ON,
283
    UNKNOWN,
284
    PLAY,
285
    PAUSE,
286
    STOP,
287
    ACTIVE,
288
    DEACTIVE,
289
    WORKING,
290
    DEFINE,
291
    UNDEFINE,
292
    LOCK,
293
    UNLOCK,
294
    EMPTY,
295
    FULL,
296
    SEND_OK,
297
    SEND_NOK
298
    //WARNING remember add new state to stateToString() usefull.cpp
299
};
300
301
302
std::string stateToString(STATE s);
303
STATE stringToState(const std::string& s);
304
305
#endif
/home/pi/programowanie/iDom_server_OOP/src/iDomTools/test/../../RADIO_433_eq/../433MHz/RFLink/../../iDom_server_OOP.h
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
4
179
    {
4
180
4
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
4
189
    {
4
190
        this->from =from;
4
191
        this->to = to;
4
192
        R = r;
4
193
        G = g;
4
194
        B = b;
4
195
        this->colorName =colorName;
4
196
    }
197
4
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
4
199
        this->from = std::to_string(from);
4
200
        this->to = std::to_string(to);
4
201
        R = std::to_string(r);
4
202
        G = std::to_string(g);
4
203
        B = std::to_string(b);
4
204
        this->colorName =colorName;
4
205
    }
206
48
207
    std::string getColorName() const{
48
208
        return colorName;
48
209
    }
210
68
211
    std::string get(unsigned int _from, unsigned int _to) const{
68
212
        if (_from != 0 || _to != 60){
36
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
36
214
        }
32
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
68
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
4
222
                            const std::string& B){
4
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
4
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    RADIO_EQ_CONTAINER *main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/home/pi/programowanie/iDom_server_OOP/src/iDomTools/test/../lightning.h
1
#ifndef LIGHTNING_H
2
#define LIGHTNING_H
3
#include <iostream>
4
5
#include "../../libs/Statistic/statistic.h"
6
#include "../../libs/useful/useful.h"
7
8
#include "idomtools_useful.h"
9
#include "json.hpp"
10
11
class CARDINAL_DIRECTIONS{
12
public:
13
    enum class CARDINAL_DIRECTIONS_ENUM{
14
        /*
15
           N
16
        NNW NNE
17
      NW       NE
18
   WNW		     ENE
19
 W				    E
20
   WSW			 ESE
21
      SW	   SE
22
        SSW	 SSE
23
           S
24
    */
25
26
        N = 1,NNE,NE,ENE,E,ESE,SE,SSE,S,SSW,SW,WSW,W,WNW,NW,NNW,ERROR
27
    };
592
28
    static CARDINAL_DIRECTIONS_ENUM stringToCardinalDirectionsEnum(std::string s){
592
29
        if (s == "N")      return CARDINAL_DIRECTIONS_ENUM::N;
588
30
        else if (s == "NNE")    return CARDINAL_DIRECTIONS_ENUM::NNE;
540
31
        else if (s == "NE")     return CARDINAL_DIRECTIONS_ENUM::NE;
516
32
        else if (s == "ENE")    return CARDINAL_DIRECTIONS_ENUM::ENE;
204
33
        else if (s == "E")      return CARDINAL_DIRECTIONS_ENUM::E;
12
34
        else if (s == "ESE")    return CARDINAL_DIRECTIONS_ENUM::ESE;
12
35
        else if (s == "SE")     return CARDINAL_DIRECTIONS_ENUM::SE;
12
36
        else if (s == "SSE")    return CARDINAL_DIRECTIONS_ENUM::SSE;
12
37
        else if (s == "S")      return CARDINAL_DIRECTIONS_ENUM::S;
12
38
        else if (s == "SSW")    return CARDINAL_DIRECTIONS_ENUM::SSW;
12
39
        else if (s == "SW")     return CARDINAL_DIRECTIONS_ENUM::SW;
12
40
        else if (s == "WSW")    return CARDINAL_DIRECTIONS_ENUM::WSW;
4
41
        else if (s == "W")      return CARDINAL_DIRECTIONS_ENUM::W;
4
42
        else if (s == "WNW")    return CARDINAL_DIRECTIONS_ENUM::WNW;
4
43
        else if (s == "NW")     return CARDINAL_DIRECTIONS_ENUM::NW;
4
44
        else if (s == "NNW")    return CARDINAL_DIRECTIONS_ENUM::NNW;
4
45
        else                    return CARDINAL_DIRECTIONS_ENUM::ERROR;
592
46
    }
47
8
48
    static std::string cardinalDirectionsEnumToString(CARDINAL_DIRECTIONS_ENUM e){
0
49
        switch (e){
0
50
        case CARDINAL_DIRECTIONS_ENUM::N:
0
51
            return "N";
0
52
        case CARDINAL_DIRECTIONS_ENUM::NNE:
0
53
            return "NNE";
0
54
        case CARDINAL_DIRECTIONS_ENUM:: NE:
0
55
            return "NE";
0
56
        case CARDINAL_DIRECTIONS_ENUM::ENE:
0
57
            return "ENE";
0
58
        case CARDINAL_DIRECTIONS_ENUM::E:
0
59
            return "E";
4
60
        case CARDINAL_DIRECTIONS_ENUM::ESE:
4
61
            return "ESE";
0
62
        case CARDINAL_DIRECTIONS_ENUM::SE:
0
63
            return "SE";
0
64
        case CARDINAL_DIRECTIONS_ENUM::SSE:
0
65
            return "SSE";
0
66
        case CARDINAL_DIRECTIONS_ENUM::S:
0
67
            return "S";
0
68
        case CARDINAL_DIRECTIONS_ENUM::SSW:
0
69
            return "SSW";
0
70
        case CARDINAL_DIRECTIONS_ENUM::SW:
0
71
            return "SW";
0
72
        case CARDINAL_DIRECTIONS_ENUM::WSW:
0
73
            return "WSW";
0
74
        case CARDINAL_DIRECTIONS_ENUM::W:
0
75
            return "W";
0
76
        case CARDINAL_DIRECTIONS_ENUM::WNW:
0
77
            return "WNW";
0
78
        case CARDINAL_DIRECTIONS_ENUM::NW:
0
79
            return "NW";
0
80
        case CARDINAL_DIRECTIONS_ENUM::NNW:
0
81
            return "NNW";
4
82
        default:
4
83
            return "UNKNOWN DIRECTION";
0
84
        }
8
85
    }
86
    static std::string cardinalDirectionsEnumToHuman(CARDINAL_DIRECTIONS_ENUM e){
87
        switch (e){
88
        case CARDINAL_DIRECTIONS_ENUM::N:
89
            return "północ";
90
        case CARDINAL_DIRECTIONS_ENUM::NNE:
91
            return "północ - północny wschód";
92
        case CARDINAL_DIRECTIONS_ENUM:: NE:
93
            return "północny wschód";
94
        case CARDINAL_DIRECTIONS_ENUM::ENE:
95
            return "wschód - północny wschód";
96
        case CARDINAL_DIRECTIONS_ENUM::E:
97
            return "wschód";
98
        case CARDINAL_DIRECTIONS_ENUM::ESE:
99
            return "wschód - południowy wschód";
100
        case CARDINAL_DIRECTIONS_ENUM::SE:
101
            return "południowy wschód";
102
        case CARDINAL_DIRECTIONS_ENUM::SSE:
103
            return "południe - południowy wschód";
104
        case CARDINAL_DIRECTIONS_ENUM::S:
105
            return "południe";
106
        case CARDINAL_DIRECTIONS_ENUM::SSW:
107
            return "południe - południowy zachów";
108
        case CARDINAL_DIRECTIONS_ENUM::SW:
109
            return "południowy zachów";
110
        case CARDINAL_DIRECTIONS_ENUM::WSW:
111
            return "zachód - południowy zachów";
112
        case CARDINAL_DIRECTIONS_ENUM::W:
113
            return "zachód";
114
        case CARDINAL_DIRECTIONS_ENUM::WNW:
115
            return "zachód - północny zachód";
116
        case CARDINAL_DIRECTIONS_ENUM::NW:
117
            return "północny zachód";
118
        case CARDINAL_DIRECTIONS_ENUM::NNW:
119
            return "północ - północny zachód";
120
        default:
121
            return "UNKNOWN DIRECTION";
122
        }
123
    }
124
    struct ALARM_INFO{
125
        ALARM_INFO():
126
            riseAlarm(false),
127
            timestamp(0),
128
            distance(0.0),
129
            bearingENG(CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ERROR)
130
        {
131
            data << "NULL";
132
        }
133
        ALARM_INFO(const ALARM_INFO &s):
134
            riseAlarm(s.riseAlarm),
135
            data(s.data.str()),
136
            timestamp(s.timestamp),
137
            distance(s.distance),
138
            bearingENG(s.bearingENG)
139
        {
140
        }
141
        ALARM_INFO& operator = (const ALARM_INFO& s)
56
142
        {
56
143
            this->data.str(std::string());
56
144
            this->riseAlarm = s.riseAlarm;
56
145
            this->data << s.data.str();
56
146
            this->timestamp = s.timestamp;
56
147
            this->distance = s.distance;
56
148
            this->bearingENG = s.bearingENG;
56
149
            return *this;
56
150
        }
151
152
        bool riseAlarm;
153
        std::stringstream data;
154
        unsigned int timestamp; //second
155
        double distance; //km
156
        CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM bearingENG;
157
    };
158
};
159
160
class LIGHTNING
161
{
162
public:
163
    LIGHTNING();
164
    ~LIGHTNING();
165
    CARDINAL_DIRECTIONS::ALARM_INFO lightningAlert(nlohmann::json jj);
166
    bool checkLightningAlert(CARDINAL_DIRECTIONS::ALARM_INFO* info);
167
private:
168
    bool alarmState = false;
169
    Clock lightningTime;
170
    double oldDistance = 0.0;
171
};
172
173
#endif // LIGHTNING_H
/home/pi/programowanie/iDom_server_OOP/src/iDomTools/test/iDom_server_BT.cpp
1
#include <gtest/gtest.h>
2
#include <curl/curl.h>
3
#include "iDomTools_fixture.h"
4
5
class iDom_server_Class : public iDomTOOLS_ClassTest
6
{
7
protected:
8
    TEST_JSON test_Json;
9
    LIGHTNING test_lightning;
10
    CARDINAL_DIRECTIONS::ALARM_INFO test_struct;
11
    virtual void SetUp() final
4
12
    {
4
13
        std::cout << "konfiguracja przed testem iDom_server_Class " <<std::endl;
4
14
    }
15
16
    virtual void TearDown() final
4
17
    {
4
18
        std::cout << "czyszczenie po tescie iDom_server_Class " <<std::endl;
4
19
    }
20
};
21
22
TEST_F(iDom_server_Class, LED_Strip )
4
23
{
4
24
    LED_Strip test_LED("1","60","255","255","255", "WHITE");
4
25
    EXPECT_STREQ(test_LED.getColorName().c_str(), "WHITE");
4
26
    EXPECT_STREQ(test_LED.get(0,60).c_str(),"LED:[1-60-255-255-255];");
4
27
    EXPECT_STREQ(test_LED.makeCommand("1","60","128","128","128").c_str(),"LED:[1-60-128-128-128];");
4
28
4
29
    test_LED.set("1","60","0","255","0","UNKNOWN");
4
30
4
31
    EXPECT_STREQ(test_LED.getColorName().c_str(), "UNKNOWN");
4
32
    EXPECT_STREQ(test_LED.get(0,60).c_str(),"LED:[1-60-0-255-0];");
4
33
4
34
    test_LED.set(50,51,1,2,3,"BLACK");
4
35
4
36
    EXPECT_STREQ(test_LED.getColorName().c_str(), "BLACK");
4
37
    EXPECT_STREQ(test_LED.get(0,60).c_str(),"LED:[50-51-1-2-3];");
4
38
}
/home/pi/programowanie/iDom_server_OOP/src/iDomTools/test/idomTools_BT.cpp
1
#include <gtest/gtest.h>
2
#include <curl/curl.h>
3
4
#include "iDomTools_fixture.h"
5
6
TEST_F(iDomTOOLS_ClassTest, smog)
4
7
{
4
8
    std::string smog = test_idomTOOLS->getSmog();
4
9
    puts(smog.c_str());
4
10
    puts(" smog");
4
11
    ASSERT_GE(smog.size(),1);
4
12
4
13
    unsigned int smog_int = std::stoi(smog);
4
14
    ASSERT_GT(smog_int,1);
4
15
    ASSERT_LT(smog_int,1000);
4
16
}
17
18
TEST_F(iDomTOOLS_ClassTest, hasTemperatureChange)
4
19
{
4
20
    std::cout << "##################################### 0" <<std::endl;
4
21
4
22
    TEST_DATA::return_send_to_arduino = "20.0:-1.0;";
4
23
    test_idomTOOLS->send_temperature_thingSpeak();
4
24
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::Under);
4
25
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::NoChanges);
4
26
    std::cout << "##################################### 1" <<std::endl;
4
27
4
28
    TEST_DATA::return_send_to_arduino = "25.4:0.0;";
4
29
    test_idomTOOLS->send_temperature_thingSpeak();
4
30
4
31
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::NoChanges);
4
32
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::Over);
4
33
4
34
    std::cout << "##################################### 2" <<std::endl;
4
35
4
36
    TEST_DATA::return_send_to_arduino = "21.0:1.0;";
4
37
    test_idomTOOLS->send_temperature_thingSpeak();
4
38
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::Over);
4
39
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::Under);
4
40
4
41
    std::cout << "##################################### 3" <<std::endl;
4
42
    TEST_DATA::return_send_to_arduino = "21.0:5.0;";
4
43
    test_idomTOOLS->send_temperature_thingSpeak();
4
44
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::NoChanges);
4
45
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::NoChanges);
4
46
4
47
    std::cout << "##################################### 4" <<std::endl;
4
48
    TEST_DATA::return_send_to_arduino = "21.0:4.0;";
4
49
    test_idomTOOLS->send_temperature_thingSpeak();
4
50
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::NoChanges);
4
51
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::NoChanges);
4
52
    std::cout << "##################################### 5" <<std::endl;
4
53
4
54
    TEST_DATA::return_send_to_arduino = "31.9:11.11;";
4
55
    test_idomTOOLS->send_temperature_thingSpeak();
4
56
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::NoChanges);
4
57
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::Over);
4
58
    std::cout << "##################################### 6" <<std::endl;
4
59
4
60
    ////// getThermoStats
4
61
4
62
    std::cout <<"WYNIK: " << test_idomTOOLS->getThermoStats("inside") <<std::endl;
4
63
}
64
65
TEST_F(iDomTOOLS_ClassTest, weatherAlert)
4
66
{
4
67
    std::string test_data_from_www = "    <div style=\"margin:0;padding:0;width:350px;font:0.8em Lucida,Arial,sans-seri                                                                  f;background:#FFC\">\
4
68
            <p style=\"margin:1px;padding:1px;text-align:center;background:#FF9;borde \                                                                 r:1px dotted\"><b><a href=\"http://burze.dzis.net?page=wyszukiwarka&amp;miejscowos\                                                                  c=krakow\" target=\"_blank\" style=\"color:#00E\">krakow</a></b>\
4
69
            <i>(50°03'N 19°57'E)</i>\
4
70
            </p>\
4
71
            <dl style=\"margin:1px 1px 0 1px;padding:0;cl                                                                  ear:both;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:\                                                                  center\">Zarejestrowano 54 wyładowania atmosferyczne w promieniu 300km . Najbliższe 79.76km na zachód.\
4
72
            </dl>\
4
73
            \
4
74
            <dl style=\"margin:1px 1px 0 1px;padding:0;cl                                                                  ear:both;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:  \                                                                center\">Mróz, brak ostrzeżeń</dl>\
4
75
            \
4
76
            <dl style=\"margin:1px 1px 0 1px;padding:0;clear:both                                                                  ;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:center\">  \                                                                Upał, brak ostrzeżeń</dl>\
4
77
            \
4
78
            <dl style=\"margin:1px 1px 0 1px;padding:0;clear:both                                                                  ;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:center\">  \                                                                Wiatr, brak ostrzeżeń</dl>\
4
79
            \
4
80
            <dl style=\"margin:1px 1px 0 1px;padding:0;clear:both                                                                  ;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:center\">  \                                                                Opady, brak ostrzeżeń</dl>\
4
81
            \
4
82
            <dl style=\"margin:1px 1px 0 1px;padding:0;clear:both                                                                  ;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:center\">  \                                                                Burze, brak ostrzeżeń</dl>\
4
83
            \
4
84
            <dl style=\"margin:1px 1px 0 1px;padding:0;clear:both                                                                  ;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:center\">  \                                                                Trąby powietrzne, brak ostrzeżeń</dl>\
4
85
            </div>";
4
86
4
87
4
88
            std::vector<WEATHER_ALER> test_WA;
4
89
    test_WA =  test_idomTOOLS->getAlert(test_data_from_www);
12
90
    EXPECT_EQ(1,test_WA.size()) << "ZŁY ROZMIAR VEKTORA WA";
4
91
}
92
4
93
TEST_F(iDomTOOLS_ClassTest, send_temperature_thingSpeak){
4
94
4
95
    TEST_DATA::return_send_to_arduino = "-2.3:-2";
4
96
    TEST_DATA::return_httpPost_expect = "NULL";
4
97
    EXPECT_STREQ(TEST_DATA::return_httpPost_expect.c_str(),"NULL");
4
98
    test_idomTOOLS->send_temperature_thingSpeak();
4
99
    std::cout << "DATA: "<< TEST_DATA::return_httpPost_expect <<std::endl;
4
100
    EXPECT_STREQ(TEST_DATA::return_httpPost_expect.c_str(),"httpPost");
4
101
}
102
103
TEST_F(iDomTOOLS_ClassTest, checkAlarm)
4
104
{
4
105
    blockQueue test_q;
4
106
    unsigned int fromVol = 48;
4
107
    unsigned int  toVol = 57;
4
108
4
109
    ///////////////////////////////////// to save
4
110
    test_status.setObjectState("house",STATE::UNLOCK);
4
111
    test_status.setObjectState("music", STATE::PLAY);
4
112
    test_status.setObjectState("speakers", STATE::ON);
4
113
    test_my_data.idom_all_state.houseState = STATE::LOCK;
4
114
4
115
    test_status.setObjectState("listwa",STATE::ON);
4
116
4
117
    test_alarmTime.time = Clock::getTime();
4
118
    test_alarmTime.state = STATE::ACTIVE;
4
119
    test_alarmTime.toVolume = 58;
4
120
    test_alarmTime.fromVolume = 48;
4
121
    test_status.setObjectState("alarm", test_alarmTime.state);
4
122
    test_my_data.alarmTime = test_alarmTime;
4
123
    useful_F::myStaticData = &test_my_data;
4
124
4
125
    //////////////////////////////////////////////////////////////
4
126
4
127
    test_my_data.alarmTime.time = Clock::getTime();
4
128
    test_my_data.alarmTime.state = STATE::ACTIVE;
4
129
4
130
    EXPECT_EQ(test_my_data.alarmTime.state, STATE::ACTIVE);
4
131
40
132
    for(unsigned int i = fromVol; i<toVol; ++i)
36
133
    {
36
134
        test_idomTOOLS->checkAlarm();
36
135
        test_q._get();
108
136
        EXPECT_EQ(test_my_data.alarmTime.state, STATE::WORKING)<< "zły stan w for " << i<< " "<< toVol;
108
137
        EXPECT_EQ(test_my_data.ptr_MPD_info->volume, i+1) << "zły poziom glosnosci w for";
36
138
    }
4
139
4
140
    test_idomTOOLS->checkAlarm();
4
141
12
142
    EXPECT_EQ(test_my_data.alarmTime.state, STATE::DEACTIVE) << "nie jest STATE::DEACTIVE";
12
143
    EXPECT_EQ(test_my_data.ptr_MPD_info->volume, toVol)<< "nie inkrementowane?";
4
144
4
145
}
146
147
TEST_F(iDomTOOLS_ClassTest, homeLockPlayStopMusic)
4
148
{
4
149
    ///////////////////////////////////// to save
4
150
    test_status.setObjectState("house",STATE::UNDEFINE);
4
151
    test_status.setObjectState("music", STATE::PLAY);
4
152
    test_status.setObjectState("speakers", STATE::ON);
4
153
    test_my_data.idom_all_state.houseState = STATE::LOCK;
4
154
4
155
    test_status.setObjectState("listwa",STATE::ON);
4
156
4
157
    test_alarmTime.time = Clock::getTime();
4
158
    test_alarmTime.state = STATE::ACTIVE;
4
159
    test_status.setObjectState("alarm", test_alarmTime.state);
4
160
4
161
    blockQueue test_q;
4
162
    test_q._clearAll();
4
163
    EXPECT_EQ(test_q._size(),0);
4
164
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNDEFINE);
4
165
    test_idomTOOLS->lockHome();
4
166
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
4
167
    test_idomTOOLS->MPD_play(&test_my_data);
4
168
    EXPECT_EQ(test_q._size(),0);
4
169
    test_idomTOOLS->unlockHome();
4
170
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
4
171
    test_idomTOOLS->MPD_play(&test_my_data);
4
172
    EXPECT_EQ(test_q._size(),1);
4
173
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
4
174
    EXPECT_EQ(test_q._size(),0);
4
175
    test_idomTOOLS->lockHome();
4
176
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
4
177
    test_idomTOOLS->MPD_stop();
4
178
    EXPECT_EQ(test_q._size(),1);
4
179
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
4
180
    EXPECT_EQ(test_q._size(),0);
4
181
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
4
182
    std::string returnedString = test_status.getAllObjectsStateString();
4
183
    EXPECT_THAT(returnedString, testing::HasSubstr("LOCK"));
4
184
}
185
186
TEST_F(iDomTOOLS_ClassTest, buttonPressed)
4
187
{
4
188
    std::string button433MHz_id = "01e7be";
4
189
    std::string pressedButtonName = test_idomTOOLS->buttonPressed(button433MHz_id);
4
190
    EXPECT_EQ(1, test_my_data.main_REC->getButtonPointerVector().size());
4
191
    EXPECT_STREQ(std::to_string(button433MHz_id).c_str(),
4
192
                 test_my_data.main_REC->getButtonPointerVector().at(0)->getID().c_str());
4
193
    EXPECT_STREQ(pressedButtonName.c_str(), "locker");
4
194
4
195
    EXPECT_THROW(test_idomTOOLS->buttonPressed(button433MHz_id+"a"),
4
196
                 std::string);
4
197
}
198
199
TEST_F(iDomTOOLS_ClassTest, button433MHzPressedAction_lockerUnlock)
4
200
{
4
201
    blockQueue test_q;
4
202
    test_q._clearAll();
4
203
4
204
    test_idomTOOLS->unlockHome();
4
205
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
4
206
12
207
    for(auto i : {1,2,3}){
12
208
        test_idomTOOLS->button433MHzPressedAction("locker");
12
209
    }
4
210
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
4
211
4
212
    EXPECT_EQ(test_q._size(),1);
4
213
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
4
214
4
215
}
216
217
TEST_F(iDomTOOLS_ClassTest, button433MHzPressedAction_lockerLock)
4
218
{
4
219
    blockQueue test_q;
4
220
    test_q._clearAll();
4
221
12
222
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNDEFINE) << "nie jest UNDEFINED";
4
223
4
224
    test_idomTOOLS->button433MHzPressedAction("locker");
12
225
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK)<< "nie jest UNLOCK";
4
226
4
227
    EXPECT_EQ(test_q._size(),1);
4
228
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
4
229
    EXPECT_EQ(test_q._size(),0);
4
230
}
231
232
TEST_F(iDomTOOLS_ClassTest, testCPU_Load)
4
233
{
4
234
    std::cout <<"TEST LOAD" << std::endl;
4
235
    std::cout << test_idomTOOLS->getSystemInfo() << std::endl;
4
236
}
237
TEST_F(iDomTOOLS_ClassTest, stringToCardinalDirectionsEnum)
4
238
{
4
239
    EXPECT_EQ(CARDINAL_DIRECTIONS::stringToCardinalDirectionsEnum("NWWA"),
4
240
              CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ERROR);
4
241
    EXPECT_EQ(CARDINAL_DIRECTIONS::stringToCardinalDirectionsEnum("N"),
4
242
              CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::N);
4
243
}
244
245
TEST_F(iDomTOOLS_ClassTest, cardinalDirectionsEnumToString)
4
246
{
4
247
    EXPECT_STREQ( CARDINAL_DIRECTIONS::cardinalDirectionsEnumToString(CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ERROR).c_str(),
4
248
                  "UNKNOWN DIRECTION");
4
249
    EXPECT_STREQ( CARDINAL_DIRECTIONS::cardinalDirectionsEnumToString(CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ESE).c_str(),
4
250
                  "ESE");
4
251
}
252
253
TEST_F(iDomTOOLS_ClassTest, saveState_readState)
4
254
{
4
255
    test_status.setObjectState("house",STATE::UNLOCK);
4
256
    //////////////////// mpd
4
257
    test_status.setObjectState("music", STATE::PLAY);
4
258
    test_status.setObjectState("speakers", STATE::ON);
4
259
    test_my_data.idom_all_state.houseState = STATE::LOCK;
4
260
4
261
    test_status.setObjectState("listwa",STATE::ON);
4
262
    test_alarmTime.time = Clock::getTime();
4
263
    test_alarmTime.state = STATE::ACTIVE;
4
264
    test_alarmTime.fromVolume = 0;
4
265
    test_alarmTime.toVolume = 100;
4
266
    test_alarmTime.radioID = 44;
4
267
    test_my_data.alarmTime = test_alarmTime;
4
268
    test_status.setObjectState("alarm", test_alarmTime.state);
4
269
4
270
    test_idomTOOLS->saveState_iDom();
4
271
4
272
    nlohmann::json testJson;
4
273
    std::ifstream i(test_server_set.saveFilePath);
4
274
    i >> testJson;
4
275
    EXPECT_STREQ(test_status.getObjectStateString("music").c_str(),
4
276
                 testJson.at("MPD").at("music").get<std::string>().c_str() );
4
277
    EXPECT_STREQ((test_status.getObjectStateString("alarm")).c_str(),
4
278
                 testJson.at("ALARM").at("alarm").get<std::string>().c_str() );
4
279
    EXPECT_EQ(test_alarmTime.radioID,
4
280
              testJson.at("ALARM").at("radioID").get<int>() );
4
281
    EXPECT_EQ(test_alarmTime.fromVolume,
4
282
              testJson.at("ALARM").at("fromVolume").get<int>() );
4
283
    EXPECT_EQ(test_alarmTime.toVolume,
4
284
              testJson.at("ALARM").at("toVolume").get<int>() );
4
285
    ////////////////////////////////// read
4
286
    test_idomTOOLS->readState_iDom();
4
287
    EXPECT_EQ(test_my_data.alarmTime.state,STATE::ACTIVE);
4
288
}
289
290
TEST_F(iDomTOOLS_ClassTest, getLightningStruct)
4
291
{
4
292
    LIGHTNING test_lightning;
4
293
    test_struct = test_lightning.lightningAlert(test_Json.jj_lightning);
4
294
4
295
    test_idomTOOLS->setLightningStruct(test_struct);
4
296
4
297
    bool test_result = test_lightning.checkLightningAlert(&test_struct);
4
298
    EXPECT_TRUE(test_result);
4
299
4
300
    auto test_alert_info = test_idomTOOLS->getLightningStruct();
4
301
    EXPECT_EQ(test_alert_info.timestamp,210);
4
302
}
303
TEST_F(iDomTOOLS_ClassTest, checkLightning)
4
304
{
4
305
    test_my_data.server_settings->lightningApiURL = "http://cyniu88.no-ip.pl/test/json/lightning.json";
4
306
    test_idomTOOLS->checkLightning();
4
307
    auto test_alert_info = test_idomTOOLS->getLightningStruct();
4
308
    EXPECT_EQ(test_alert_info.timestamp,210);
4
309
}
310
311
TEST_F(iDomTOOLS_ClassTest, updateTemperatureStats)
4
312
{
4
313
    TEST_DATA::return_send_to_arduino = "12:12";
4
314
    test_idomTOOLS->updateTemperatureStats();
4
315
    TEST_DATA::return_send_to_arduino = "16:16";
4
316
    test_idomTOOLS->updateTemperatureStats();
4
317
4
318
    ////////////// maleje na mieskzaniu
4
319
    TEST_DATA::return_send_to_arduino = "12:16";
4
320
    test_idomTOOLS->updateTemperatureStats();
4
321
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("temperatura maleje"));
4
322
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("mieszkaniu"));
4
323
4
324
    ////////////// maleje na polu
4
325
    TEST_DATA::return_send_to_arduino = "12:12";
4
326
    test_idomTOOLS->updateTemperatureStats();
4
327
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("temperatura maleje"));
4
328
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("polu"));
4
329
4
330
    ////////////// rośnie na mieskzaniu
4
331
    TEST_DATA::return_send_to_arduino = "17:12";
4
332
    test_idomTOOLS->updateTemperatureStats();
4
333
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("temperatura rośnie"));
4
334
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("mieszkaniu"));
4
335
4
336
    ////////////// rośnie na polu
4
337
    TEST_DATA::return_send_to_arduino = "17:17";
4
338
    test_idomTOOLS->updateTemperatureStats();
4
339
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("temperatura rośnie"));
4
340
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("polu"));
4
341
}
342
343
TEST_F(iDomTOOLS_ClassTest, speakersON_OFF)
4
344
{
4
345
    EXPECT_EQ(test_status.getObjectState("speakers"), STATE::OFF);
4
346
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
4
347
    test_idomTOOLS->turnOnSpeakers();
4
348
    EXPECT_EQ(test_status.getObjectState("speakers"), STATE::ON);
4
349
    test_idomTOOLS->turnOffSpeakers();
4
350
    EXPECT_EQ(test_status.getObjectState("speakers"), STATE::OFF);
4
351
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
4
352
    test_idomTOOLS->turnOnSpeakers();
4
353
    EXPECT_EQ(test_status.getObjectState("speakers"), STATE::OFF);
4
354
    std::string retStr = useful_F::myStaticData->myEventHandler.run("speakers")->getEvent();
4
355
    EXPECT_THAT(retStr, testing::HasSubstr("speakers can not start due to home state: LOCK"));
4
356
}
357
358
TEST_F(iDomTOOLS_ClassTest, printerON_OFF)
4
359
{
4
360
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
4
361
    test_idomTOOLS->turnOnPrinter();
4
362
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::ON);
4
363
    test_idomTOOLS->turnOffPrinter();
4
364
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::OFF);
4
365
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
4
366
    test_idomTOOLS->turnOnPrinter();
4
367
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::OFF);
4
368
    std::string retStr = useful_F::myStaticData->myEventHandler.run("230V")->getEvent();
4
369
    EXPECT_THAT(retStr, testing::HasSubstr("Printer can not start due to home state: LOCK"));
4
370
}
371
372
TEST_F(iDomTOOLS_ClassTest, getPinState)
4
373
{
4
374
    setReturnPinState(0);
4
375
    EXPECT_EQ(test_idomTOOLS->getPinState(0), PIN_STATE::LOW_STATE);
4
376
    setReturnPinState(1);
4
377
    EXPECT_EQ(test_idomTOOLS->getPinState(0), PIN_STATE::HIGH_STATE);
4
378
    setReturnPinState(4);
4
379
    EXPECT_EQ(test_idomTOOLS->getPinState(0), PIN_STATE::UNKNOWN_STATE);
4
380
}
381
382
TEST_F(iDomTOOLS_ClassTest, turnOnOffPrinter)
4
383
{
4
384
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
4
385
    test_status.setObjectState("printer",STATE::ON);
4
386
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::ON);
4
387
    setReturnPinState(1);
4
388
    puts("off printer");
4
389
    test_idomTOOLS->turnOnOffPrinter();
4
390
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::OFF);
4
391
    setReturnPinState(0);
4
392
    puts("on printer");
4
393
    test_idomTOOLS->turnOnOffPrinter();
4
394
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::ON);
4
395
    setReturnPinState(4);
4
396
    test_idomTOOLS->turnOnOffPrinter();
4
397
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::ON);
4
398
}
399
400
TEST_F(iDomTOOLS_ClassTest, turn_On_Off_433MHzSwitch)
4
401
{
4
402
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
4
403
    EXPECT_EQ(test_status.getObjectState("B"),STATE::UNKNOWN);
4
404
    test_idomTOOLS->turnOn433MHzSwitch("B");
4
405
    EXPECT_EQ(test_status.getObjectState("B"),STATE::ON);
4
406
    test_idomTOOLS->turnOff433MHzSwitch("B");
4
407
    EXPECT_EQ(test_status.getObjectState("B"),STATE::OFF);
4
408
}
409
410
TEST_F(iDomTOOLS_ClassTest, turnOnOff433MHzSwitch)
4
411
{
4
412
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
4
413
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("B"),STATE::UNKNOWN);
4
414
    test_my_data.main_iDomStatus->setObjectState("B",STATE::ON);
4
415
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("B"),STATE::ON);
4
416
    test_idomTOOLS->turnOnOff433MHzSwitch("B");
4
417
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("B"),STATE::OFF);
4
418
    test_idomTOOLS->turnOnOff433MHzSwitch("B");
4
419
    EXPECT_EQ(test_status.getObjectState("B"),STATE::ON);
4
420
4
421
}
422
423
TEST_F(iDomTOOLS_ClassTest, runOnSunset)
4
424
{
4
425
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
4
426
    test_idomTOOLS->runOnSunset();
4
427
    std::string retStr = useful_F::myStaticData->myEventHandler.run("iDom")->getEvent();
4
428
    EXPECT_THAT(retStr, testing::HasSubstr("433MHz can not start due to home state: LOCK"));
4
429
4
430
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
4
431
    auto ptr = static_cast<RADIO_SWITCH*>(test_my_data.main_REC->getEqPointer("B"));
4
432
    ptr->m_state = STATE::ON;
4
433
    test_idomTOOLS->runOnSunset();
4
434
4
435
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::OFF);
4
436
4
437
    RADIO_EQ_CONFIG cfg;
4
438
    cfg.sunset = "on";
4
439
    cfg.sunrise = "off";
4
440
4
441
    ptr->setCode(cfg);
4
442
    ptr->m_state = STATE::OFF;
4
443
    test_idomTOOLS->runOnSunset();
4
444
4
445
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::ON);
4
446
}
447
448
TEST_F(iDomTOOLS_ClassTest, runOnSunrise)
4
449
{
4
450
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
4
451
    test_idomTOOLS->runOnSunrise();
4
452
    std::string retStr = useful_F::myStaticData->myEventHandler.run("iDom")->getEvent();
4
453
    EXPECT_THAT(retStr, testing::HasSubstr("433MHz can not start due to home state: LOCK"));
4
454
4
455
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
4
456
    auto ptr = static_cast<RADIO_SWITCH*>(test_my_data.main_REC->getEqPointer("B"));
4
457
    ptr->m_state = STATE::OFF;
4
458
    test_idomTOOLS->runOnSunrise();
4
459
4
460
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::ON);
4
461
4
462
    RADIO_EQ_CONFIG cfg;
4
463
    cfg.sunset = "off";
4
464
    cfg.sunrise = "on";
4
465
4
466
    ptr->setCode(cfg);
4
467
4
468
    cfg.sunset = "on";
4
469
    cfg.sunrise = "off";
4
470
4
471
    ptr->setCode(cfg);
4
472
    ptr->m_state = STATE::ON;
4
473
    test_idomTOOLS->runOnSunrise();
4
474
4
475
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::OFF);
4
476
}
477
478
TEST_F(iDomTOOLS_ClassTest, getSunrise_Sunset)
4
479
{
4
480
    std::string ret = test_idomTOOLS->getSunrise();
4
481
    EXPECT_THAT(ret, testing::HasSubstr(":"));
4
482
4
483
    ret = test_idomTOOLS->getSunset();
4
484
    EXPECT_THAT(ret, testing::HasSubstr(":"));
4
485
4
486
    ret = test_idomTOOLS->getSunrise(true);
4
487
    EXPECT_THAT(ret, testing::HasSubstr("Sunrise time:"));
4
488
4
489
    ret = test_idomTOOLS->getSunset(true);
4
490
    EXPECT_THAT(ret, testing::HasSubstr("Sunset time:"));
4
491
}
492
493
TEST_F(iDomTOOLS_ClassTest, getDayLenght)
4
494
{
4
495
    std::string ret = test_idomTOOLS->getDayLenght();
4
496
    EXPECT_THAT(ret, testing::HasSubstr(":"));
4
497
4
498
    ret = test_idomTOOLS->getDayLenght(true);
4
499
    EXPECT_THAT(ret, testing::HasSubstr("Day Lenght :"));
4
500
}
501
502
TEST_F(iDomTOOLS_ClassTest, getTextToSpeach)
4
503
{
4
504
    TEST_DATA::return_send_to_arduino = "22:23";
4
505
    std::string ret = test_idomTOOLS->getTextToSpeach();
4
506
    EXPECT_THAT(ret, testing::HasSubstr("Smog:"));
4
507
    std::cout << "TEXT :"<< std::endl << ret << std::endl;
4
508
}
509
510
TEST_F(iDomTOOLS_ClassTest, mpd)
4
511
{
4
512
    MPD_info test_ptr_MPD;
4
513
    test_ptr_MPD.volume = 3;
4
514
    test_my_data.ptr_MPD_info = &test_ptr_MPD;
4
515
    blockQueue test_q;
4
516
    test_q._clearAll();
4
517
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
4
518
    test_idomTOOLS->MPD_play(&test_my_data);
4
519
    std::string retStr = useful_F::myStaticData->myEventHandler.run("MPD")->getEvent();
4
520
    EXPECT_THAT(retStr, testing::HasSubstr("MPD can not start due to home state: LOCK"));
4
521
    EXPECT_EQ(test_q._size(), 0);
4
522
4
523
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
4
524
    test_idomTOOLS->MPD_play(&test_my_data);
4
525
    EXPECT_EQ(test_q._size(), 1);
4
526
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
4
527
    EXPECT_EQ(test_q._size(), 0);
4
528
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4
529
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
4
530
4
531
    useful_F::myStaticData->myEventHandler.run("MPD")->clearEvent();
4
532
    test_idomTOOLS->MPD_play(&test_my_data,2);
4
533
    retStr = useful_F::myStaticData->myEventHandler.run("MPD")->getEvent();
4
534
    EXPECT_THAT(retStr, testing::HasSubstr("MPD can not start due to home state: LOCK"));
4
535
    EXPECT_EQ(test_q._size(), 0);
4
536
4
537
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
4
538
    test_idomTOOLS->MPD_play(&test_my_data,2);
4
539
    EXPECT_EQ(test_q._size(), 1);
4
540
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY_ID);
4
541
    EXPECT_EQ(test_q._size(), 0);
4
542
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4
543
4
544
    test_idomTOOLS->MPD_stop();
4
545
    EXPECT_EQ(test_q._size(), 1);
4
546
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
4
547
    EXPECT_EQ(test_q._size(), 0);
4
548
4
549
    test_idomTOOLS->MPD_next();
4
550
    EXPECT_EQ(test_q._size(), 1);
4
551
    EXPECT_EQ(test_q._get(), MPD_COMMAND::NEXT);
4
552
    EXPECT_EQ(test_q._size(), 0);
4
553
4
554
    test_idomTOOLS->MPD_prev();
4
555
    EXPECT_EQ(test_q._size(), 1);
4
556
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PREV);
4
557
    EXPECT_EQ(test_q._size(), 0);
4
558
4
559
    test_idomTOOLS->MPD_pause();
4
560
    EXPECT_EQ(test_q._size(), 1);
4
561
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PAUSE );
4
562
    EXPECT_EQ(test_q._size(), 0);
4
563
4
564
    test_idomTOOLS->MPD_volumeUp();
4
565
    EXPECT_EQ(test_q._size(), 1);
4
566
    EXPECT_EQ(test_q._get(), MPD_COMMAND::VOLUP );
4
567
    EXPECT_EQ(test_q._size(), 0);
4
568
4
569
    test_idomTOOLS->MPD_volumeDown();
4
570
    EXPECT_EQ(test_q._size(), 1);
4
571
    EXPECT_EQ(test_q._get(), MPD_COMMAND::VOLDOWN );
4
572
    EXPECT_EQ(test_q._size(), 0);
4
573
4
574
    test_idomTOOLS->MPD_volumeSet(&test_my_data, 99);
4
575
    EXPECT_EQ(test_q._size(), 1);
4
576
    EXPECT_EQ(test_q._get(), MPD_COMMAND::VOLSET );
4
577
    EXPECT_EQ(test_q._size(), 0);
4
578
    EXPECT_EQ(test_my_data.ptr_MPD_info->volume, 99);
4
579
4
580
    EXPECT_EQ(test_idomTOOLS->MPD_getVolume(&test_my_data),99);
4
581
4
582
}
583
584
TEST_F(iDomTOOLS_ClassTest, getTemperatureString)
4
585
{
4
586
    TEST_DATA::return_send_to_arduino = "-2:2";
4
587
    EXPECT_STREQ(test_my_data.main_iDomTools->getTemperatureString().c_str(), "-2:2");
4
588
}
589
590
TEST_F(iDomTOOLS_ClassTest, cameraLED)
4
591
{
4
592
    TEST_DATA::return_httpPost = "ok.\n";
4
593
    test_my_data.main_iDomTools->cameraLedOFF("test_link");
4
594
4
595
    ///////////////////////////////at day
4
596
    Clock::setTime_forBT_usage(12,12);
4
597
    test_my_data.main_iDomTools->cameraLedON("test_link");
4
598
4
599
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"), STATE::OFF);
4
600
    ////////////////////////////////////// at night
4
601
    Clock::setTime_forBT_usage(2,2);
4
602
    test_my_data.main_iDomTools->cameraLedON("test_link");
4
603
4
604
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"), STATE::ON);
4
605
}
606
607
TEST_F(iDomTOOLS_ClassTest, textToSpeach)
4
608
{
4
609
    test_my_data.ptr_MPD_info->isPlay = true;
4
610
    test_my_data.main_iDomStatus->setObjectState("speakers", STATE::UNDEFINE);
4
611
4
612
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::UNDEFINE);
4
613
    std::vector<std::string> test_v;
4
614
    test_my_data.main_iDomTools->textToSpeach(&test_v); //empty
4
615
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::UNDEFINE);
4
616
4
617
    test_v = {"test","msg","clock"};
4
618
    test_my_data.ptr_MPD_info->isPlay = true;
4
619
    test_my_data.main_iDomTools->textToSpeach(&test_v);
4
620
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::UNDEFINE);
4
621
    test_my_data.ptr_MPD_info->isPlay = false;
4
622
    test_my_data.main_iDomTools->textToSpeach(&test_v);
4
623
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::OFF);
4
624
}
625
626
TEST_F(iDomTOOLS_ClassTest, getWeatherEvent)
4
627
{
4
628
    TEST_DATA::return_httpPost = "httpPost";
4
629
    std::string retStr = test_my_data.main_iDomTools->getWeatherEvent("test",10);
4
630
    EXPECT_STREQ(retStr.c_str(),"httpPost");
4
631
}
632
633
TEST_F(iDomTOOLS_ClassTest, isItDay)
4
634
{
4
635
    Clock::setTime_forBT_usage(12,12);
4
636
    EXPECT_TRUE(test_my_data.main_iDomTools->isItDay());
4
637
    Clock::setTime_forBT_usage(2,12);
4
638
    EXPECT_FALSE(test_my_data.main_iDomTools->isItDay());
4
639
}
640
641
TEST_F(iDomTOOLS_ClassTest, ledClear)
4
642
{
4
643
    TEST_DATA::return_send_to_arduino = "done";
4
644
    std::string retStr = test_my_data.main_iDomTools->ledClear();
4
645
    EXPECT_STREQ(retStr.c_str(),"done");
4
646
}
647
648
TEST_F(iDomTOOLS_ClassTest, getAllDataSunrisesunset)
4
649
{
4
650
    EXPECT_THAT(test_my_data.main_iDomTools->getAllDataSunrisesunset(),
4
651
                testing::HasSubstr("Days until Y2K"));
4
652
}
/home/pi/programowanie/iDom_server_OOP/src/iDomTools/test/lightning_BT.cpp
1
#include <gtest/gtest.h>
2
3
#include "test_data.h"
4
#include "testJSON.h"
5
#include "../idomtools.h"
6
7
class lightning_Class : public ::testing::Test
8
{
9
protected:
10
    TEST_JSON test_Json;
11
    LIGHTNING test_lightning;
12
    CARDINAL_DIRECTIONS::ALARM_INFO test_struct;
13
    virtual void SetUp() final
20
14
    {
20
15
        std::cout << "konfiguracja przed testem lightning_Class " <<std::endl;
20
16
    }
17
18
    virtual void TearDown() final
20
19
    {
20
20
        std::cout << "czyszczenie po tescie lightning_Class " <<std::endl;
20
21
    }
22
};
23
24
TEST_F(lightning_Class, lightningAlertOFF)
4
25
{
4
26
    test_struct = test_lightning.lightningAlert(test_Json.jj_noLightning);
4
27
    std::cout <<std::endl << test_struct.data.str();
12
28
    EXPECT_FALSE(test_struct.riseAlarm) << "BRAK ALARMU";
4
29
}
30
31
TEST_F(lightning_Class, lightningAlertON)
4
32
{
4
33
    test_struct = test_lightning.lightningAlert(test_Json.jj_lightning);
4
34
    std::cout <<std::endl << test_struct.data.str();
12
35
    EXPECT_TRUE(test_struct.riseAlarm) << "BRAK ALARMU";
4
36
}
37
38
TEST_F(lightning_Class, checkLightningAlert)
4
39
{
4
40
4
41
    nlohmann::json test_Json2 = useful_F_libs::getJson("http://cyniu88.no-ip.pl/test/json/on_lightning.json");
4
42
    test_struct = test_lightning.lightningAlert(test_Json.jj_noLightning);
4
43
4
44
    bool test_result = test_lightning.checkLightningAlert(&test_struct);
4
45
12
46
    EXPECT_FALSE(test_result) << "BRAK ALARMU 1";
4
47
    test_struct = test_lightning.lightningAlert(test_Json2);
4
48
    test_result = test_lightning.checkLightningAlert(&test_struct);
12
49
    EXPECT_TRUE(test_result) << "BRAK ALARMU 2";
4
50
    test_result = test_lightning.checkLightningAlert(&test_struct);
12
51
    EXPECT_FALSE(test_result) << "BRAK ALARMU 3";
4
52
    test_struct.riseAlarm = false;
4
53
    test_result = test_lightning.checkLightningAlert(&test_struct);
12
54
    EXPECT_FALSE(test_result) << "BRAK ALARMU 4";
4
55
    test_struct.riseAlarm = false;
4
56
    test_result = test_lightning.checkLightningAlert(&test_struct);
12
57
    EXPECT_FALSE(test_result) << "BRAK ALARMU 5";
4
58
}
59
60
TEST_F(lightning_Class, checkLightningAlert_stormCloser)
4
61
{
4
62
    nlohmann::json test_Json2 = useful_F_libs::getJson("http://cyniu88.no-ip.pl/test/json/on_lightning.json");
4
63
4
64
    test_struct = test_lightning.lightningAlert(test_Json.jj_noLightning);
4
65
    bool test_result = test_lightning.checkLightningAlert(&test_struct);
12
66
    EXPECT_FALSE(test_result) << "BRAK ALARMU 1";
4
67
4
68
    test_struct = test_lightning.lightningAlert(test_Json2);
4
69
    test_result = test_lightning.checkLightningAlert(&test_struct);
12
70
    EXPECT_TRUE(test_result) << "BRAK ALARMU 2";
4
71
4
72
    test_result = test_lightning.checkLightningAlert(&test_struct);
12
73
    EXPECT_FALSE(test_result) << "BRAK ALARMU 3";
4
74
4
75
    test_struct = test_lightning.lightningAlert(test_Json.jj_lightning_lt15km);
4
76
    test_result = test_lightning.checkLightningAlert(&test_struct);
12
77
    EXPECT_TRUE(test_result) << "BRAK ALARMU 4";
4
78
4
79
    test_struct = test_lightning.lightningAlert(test_Json.jj_lightning_lt15km);
4
80
    test_result = test_lightning.checkLightningAlert(&test_struct);
12
81
    EXPECT_FALSE(test_result) << "BRAK ALARMU 5";
4
82
4
83
    test_struct = test_lightning.lightningAlert(test_Json.jj_noLightning);
4
84
    test_result = test_lightning.checkLightningAlert(&test_struct);
12
85
    EXPECT_FALSE(test_result) << "BRAK ALARMU 6";
4
86
4
87
    test_struct = test_lightning.lightningAlert(test_Json.jj_lightning_lt15km);
4
88
    test_result = test_lightning.checkLightningAlert(&test_struct);
12
89
    EXPECT_TRUE(test_result) << "BRAK ALARMU 7";
4
90
}
91
92
TEST_F(lightning_Class, oneLightning)
4
93
{
4
94
    test_struct = test_lightning.lightningAlert(test_Json.jj_oneLightning);
4
95
    bool test_result = test_lightning.checkLightningAlert(&test_struct);
4
96
    EXPECT_FALSE(test_result);
4
97
}
/home/pi/programowanie/iDom_server_OOP/src/logger/logger.cc
1
/*
2
 * logger.cc
3
 *
4
 *
5
 * Logger Library
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 * 
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to 
12
 * deal in the Software without restriction, including without limitation the 
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice, 
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice, 
21
 *    this list of conditions and the following disclaimer in the documentation 
22
 *    and/or other materials provided with the distribution, and in the same 
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must 
26
 *    include the following acknowledgment: "This product includes software 
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same 
28
 *    place and form as other third-party acknowledgments. Alternately, this 
29
 *    acknowledgment may appear in the software itself, in the same form and 
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or 
34
 *    other dealings in this Software without prior written authorization from 
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
44
 * THE SOFTWARE.
45
 *
46
 */
47
48
#include "logger.hpp"
49
50
pthread_mutex_t Logger::mutex_log = PTHREAD_MUTEX_INITIALIZER;
51
52
Logger::Logger(const char *f) : _file(f, std::ios::out | std::ios::app), 
53
				_log(_file),
54
				_level(INFO),
55
				_line_level(VERBOSE)
0
56
{
0
57
  assert(_file.is_open());
0
58
}
59
60
61
Logger::Logger(const std::string& f) : _file(f.c_str(), std::ios::out | std::ios::app), 
62
				       _log(_file),
63
				       _level(INFO),
64
				       _line_level(VERBOSE)
0
65
{
0
66
  assert(_file.is_open());
0
67
}
68
69
70
Logger::~Logger()
0
71
{
0
72
  if (_file.is_open()) {
0
73
    _log.flush();
0
74
    _file.close();
0
75
  }
0
76
}
77
78
void Logger::set_level(const logger_level& level)
0
79
{
0
80
  _level = level;
0
81
}  
82
 
83
84
void Logger::flush()
282
85
{
282
86
  if (_line_level >= _level) {
265
87
    _log << get_time() << " -- [" << level_str(_line_level) << "] -- " << str();
265
88
    _log.flush();
265
89
  }
282
90
  else
17
91
  {
17
92
      _log << get_time() << " -- [" << level_str(_line_level) << "] -- " << str();
17
93
      _log.flush();
17
94
  }
282
95
282
96
  str("");
282
97
  _line_level = VERBOSE;
282
98
}
99
100
101
Logger& Logger::operator<<(const logger_level& level)
277
102
{
277
103
  _line_level = level;
277
104
  return (*this);
277
105
}
106
107
108
Logger& Logger::operator<<(LoggerManip m)
282
109
{ 
282
110
  return m(*this);
282
111
}
112
113
114
std::string Logger::get_time() const
282
115
{
282
116
  struct tm *timeinfo;
282
117
  time_t rawtime;
282
118
  char *time_buf;
282
119
  
282
120
  time(&rawtime);
282
121
  timeinfo = localtime(&rawtime);
282
122
  time_buf = asctime(timeinfo);
282
123
  
282
124
  std::string ret(time_buf);
282
125
  if (!ret.empty() && ret[ret.length() - 1] == '\n') {
282
126
    ret.erase(ret.length()-1);
282
127
  }
282
128
  
282
129
  return (ret);
282
130
}
131
132
133
inline const char* Logger::level_str(const logger_level& level)
282
134
{
0
135
  switch (level) {
5
136
  case VERBOSE:
5
137
    return ("VERBOSE ");
12
138
  case DEBUG:
12
139
    return (" DEBUG  ");
189
140
  case INFO:
189
141
    return ("  INFO  ");
16
142
  case WARNING:
16
143
    return ("WARNING ");
24
144
  case ERROR:
24
145
    return (" ERROR  ");
36
146
  case CRITICAL:
36
147
    return ("CRITICAL");
0
148
  case FATAL:
0
149
    return (" FATAL  ");
0
150
  default:
0
151
    assert(false);
0
152
  } 
282
153
}
154
void Logger::mutex_lock()
277
155
{
277
156
    pthread_mutex_lock(&Logger::mutex_log);
277
157
}
158
159
void Logger::mutex_unlock()
277
160
{
277
161
    pthread_mutex_unlock(&Logger::mutex_log);
277
162
}
/home/pi/programowanie/iDom_server_OOP/src/menu_tree/menu_tree.cpp
1
#include "menu_tree.h"
2
3
menu_tree::menu_tree (const std::string &path, LCD_c *mainLCD_PTR):database_path(path),w_serial( "([Ss]\\d{1,3}[Ee]\\d{1,3})")
48
4
{
48
5
    mainLCD=mainLCD_PTR;
48
6
48
7
    i_stack.push(0);
48
8
    i=0;
48
9
    get_list(database_path);
48
10
}
11
12
bool menu_tree::is_file() const
28
13
{
28
14
    return movie_database_vector[i].is_file;
28
15
}
16
//std::string menu_tree::return_path( int i) const
17
//{
18
19
//    return movie_database_vector[i].path;
20
//}
21
22
//void menu_tree::get_main_list()
23
//{
24
//    get_list( database_path );
25
//}
26
void menu_tree::next()
92
27
{   
92
28
    ++i;
92
29
    if (get_vector_size() == i ){
8
30
        i=0;
8
31
    }
92
32
}
33
34
void menu_tree::previous()
24
35
{
24
36
    --i;
24
37
    if ( i <0 )
4
38
    {
4
39
        i=get_vector_size()-1;
4
40
    }
24
41
}
42
43
int menu_tree::get_vector_size () const
96
44
{
96
45
    return movie_database_vector.size();
96
46
}
47
void menu_tree::vector_clear ()
56
48
{
56
49
    movie_database_vector.clear();
56
50
}
51
int menu_tree::get_i()
4
52
{
4
53
    if (i_stack.size() >1 ) {
4
54
        int i = i_stack.top();
4
55
        i_stack.pop();
4
56
        return i;
4
57
    }
4
58
    else
0
59
        return 0;
4
60
}
61
62
void menu_tree::enter_dir()
4
63
{
4
64
    i_stack.push(i); // wpisuje na stos kolejna wersje licznika i
4
65
    
4
66
    if (movie_database_vector[i].is_file == true ) {
0
67
0
68
    }
4
69
    else {
4
70
        get_list (movie_database_vector[i].path);
4
71
        i=0;
4
72
    }
4
73
}
74
//void menu_tree::enter_dir(const std::string& path)
75
//{
76
//    get_list (path) ;
77
//}
78
79
void menu_tree::back_dir()
4
80
{
4
81
    if ( tree_stack.size() >1 ) {
4
82
        tree_stack.pop();
4
83
        std::string path = tree_stack.top();
4
84
        tree_stack.pop();
4
85
        i=get_i();
4
86
        get_list (path);
4
87
        return;
4
88
    }
0
89
    i=get_i();
0
90
    get_list (database_path);
0
91
    return;
4
92
}
93
94
std::string menu_tree::show_list()
240
95
{
240
96
    if (movie_database_vector[i].is_file == true ) {
160
97
        mainLCD->printString(true,0,0,movie_database_vector[i].files_name.substr(0,16));
160
98
160
99
        return movie_database_vector[i].files_name;
160
100
    }
80
101
    else {
80
102
        mainLCD->printString(true,0,0,movie_database_vector[i].files_name+" ->");
80
103
    }
240
104
80
105
    return movie_database_vector[i].path;
240
106
}
107
bool comper (const movie_database & a , const movie_database& b);
108
//{
109
//    return a.files_name < b.files_name;
110
//}
111
56
112
void menu_tree::get_list(const std::string& path) {
56
113
    tree_stack.push(path);
56
114
    vector_clear(); // czyscimy vector
56
115
    std::string path2 =path;
56
116
    std::string v_path ,tmp_string;
56
117
    if(sciezka = opendir( path.c_str() )) {
52
118
52
119
416
120
        while(( plik = readdir( sciezka ) ) )
364
121
        {
364
122
            path2 =path;
364
123
            if (static_cast<int>(plik->d_type) == 4 /*&& strcmp( plik->d_name, "..") && strcmp( plik->d_name, ".")*/ )
208
124
            {
208
125
                if (!strcmp( plik->d_name, "..") || !strcmp( plik->d_name, "."))
104
126
                {continue;}
104
127
                temp.is_file=false;
104
128
            }
364
129
            else //if ( (int)plik->d_type == 8 && strcmp( plik->d_name, "..") && strcmp( plik->d_name, "."))
156
130
            {
156
131
                temp.is_file=true;
156
132
            }
364
133
260
134
            v_path= path2;
260
135
            v_path+="/";
260
136
            tmp_string.assign(plik->d_name);
260
137
            v_path+=tmp_string;
260
138
            temp.path =v_path;
260
139
            temp.files_name.assign(plik->d_name);
260
140
            movie_database_vector.push_back(temp);
260
141
260
142
        } // end while
52
143
        sort(movie_database_vector.begin(),movie_database_vector.end(), comper);
52
144
        closedir( sciezka );
52
145
    }
56
146
}
/home/pi/programowanie/iDom_server_OOP/src/thread_functions/../functions/../blockQueue/../logger/logger.hpp
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
56
84
    {
56
85
        *static_cast<std::ostringstream *>(this) << t;
56
86
        return (*this);
56
87
    }
_ZN6LoggerlsIA7_cEERS_RKT_
12
84
    {
12
85
        *static_cast<std::ostringstream *>(this) << t;
12
86
        return (*this);
12
87
    }
_ZN6LoggerlsINSt6thread2idEEERS_RKT_
12
84
    {
12
85
        *static_cast<std::ostringstream *>(this) << t;
12
86
        return (*this);
12
87
    }
_ZN6LoggerlsIA26_cEERS_RKT_
12
84
    {
12
85
        *static_cast<std::ostringstream *>(this) << t;
12
86
        return (*this);
12
87
    }
_ZN6LoggerlsIA3_cEERS_RKT_
4
84
    {
4
85
        *static_cast<std::ostringstream *>(this) << t;
4
86
        return (*this);
4
87
    }
_ZN6LoggerlsIPKcEERS_RKT_
0
84
    {
0
85
        *static_cast<std::ostringstream *>(this) << t;
0
86
        return (*this);
0
87
    }
_ZN6LoggerlsIA15_cEERS_RKT_
16
84
    {
16
85
        *static_cast<std::ostringstream *>(this) << t;
16
86
        return (*this);
16
87
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/home/pi/programowanie/iDom_server_OOP/src/thread_functions/../functions/../c_connection/../iDom_server_OOP.h
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
164
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
56
41
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    RADIO_EQ_CONTAINER *main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/home/pi/programowanie/iDom_server_OOP/src/thread_functions/TEST/../../c_connection/../functions/../blockQueue/../logger/logger.hpp
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
48
84
    {
48
85
        *static_cast<std::ostringstream *>(this) << t;
48
86
        return (*this);
48
87
    }
_ZN6LoggerlsIA22_cEERS_RKT_
16
84
    {
16
85
        *static_cast<std::ostringstream *>(this) << t;
16
86
        return (*this);
16
87
    }
_ZN6LoggerlsIA2_cEERS_RKT_
32
84
    {
32
85
        *static_cast<std::ostringstream *>(this) << t;
32
86
        return (*this);
32
87
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/home/pi/programowanie/iDom_server_OOP/src/thread_functions/TEST/../rs232_thread.h
1
#ifndef RS232_THREAD_H
2
#define RS232_THREAD_H
3
4
#include "../c_connection/c_connection.h"
5
#include "../TASKER/tasker.h"
6
#include "../SerialPi/serialpi.h"
7
#include "../thread_functions/iDom_thread.h"
8
9
//////////// watek wysylajacy/obdbierajacy dane z portu RS232 ////////
16
10
void Send_Recieve_rs232_thread (thread_data_rs232 *data_rs232, const std::string& threadName){
16
11
16
12
    SerialPi serial_ardu(data_rs232->portRS232);
16
13
    serial_ardu.begin( std::stoi( data_rs232->BaudRate));
16
14
16
15
    log_file_mutex.mutex_lock();
16
16
    log_file_cout << INFO <<"otwarcie portu RS232 " << data_rs232->portRS232 << " " <<data_rs232->BaudRate<<std::endl;
16
17
    log_file_mutex.mutex_unlock();
16
18
16
19
    SerialPi serial_ardu_clock(data_rs232->portRS232_clock);
16
20
    serial_ardu_clock.begin( std::stoi( data_rs232->BaudRate));
16
21
16
22
    log_file_mutex.mutex_lock();
16
23
    log_file_cout << INFO <<"otwarcie portu RS232_clock " << data_rs232->portRS232_clock <<" "<< data_rs232->BaudRate <<std::endl;
16
24
    log_file_mutex.mutex_unlock();
16
25
16
26
    /////////////////////////////////////////////////// RESET ARDUINO AFTER RESTART ////////////////////////////////
16
27
    puts("restart arduino\n");
16
28
    //C_connection::mutex_who.lock();
16
29
    {
16
30
        std::lock_guard<std::mutex> lockWho(useful_F::mutex_who);
16
31
        buffer = "reset:00;";
16
32
        serial_ardu.print(buffer.c_str());
16
33
    }
16
34
    //C_connection::mutex_who.unlock();
16
35
    //puts("test testo po lock");
16
36
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16
37
    while(useful_F::go_while)
16
38
    {
16
39
        std::this_thread::sleep_for( std::chrono::milliseconds(50));
16
40
        //puts("test testo po lock");
16
41
        { //mutex who
16
42
            std::lock_guard<std::mutex> lockWho(useful_F::mutex_who);
16
43
16
44
            if(data_rs232->pointer.ptr_who[0] == iDomConst::RS232)
4
45
            {
4
46
                std::lock_guard<std::mutex> lockBuf(useful_F::mutex_buf);
4
47
                data_rs232->pointer.ptr_who[0] = data_rs232->pointer.ptr_who[1];
4
48
                data_rs232->pointer.ptr_who[1] = iDomConst::RS232;
4
49
                serial_ardu.print(buffer.c_str());
4
50
4
51
                buffer.erase();
4
52
12
53
                while(useful_F::go_while){
12
54
                    if(serial_ardu.available()>0){
12
55
                        buffer += serial_ardu.read();
12
56
                    }
12
57
                    if(buffer[buffer.size()-1] == ';')
4
58
                    {
4
59
                        buffer.erase(buffer.end()-1);
4
60
                        break;
4
61
                    }
12
62
                }
4
63
#ifdef BT_TEST
4
64
                useful_F::go_while = false;
4
65
                return;
4
66
#endif
4
67
            }
12
68
            else if(data_rs232->pointer.ptr_who[0] == iDomConst::CLOCK)
8
69
            {
8
70
                std::lock_guard<std::mutex> lockBuf(useful_F::mutex_buf);
8
71
                data_rs232->pointer.ptr_who[0] = data_rs232->pointer.ptr_who[1];
8
72
                data_rs232->pointer.ptr_who[1] = iDomConst::CLOCK;
8
73
                serial_ardu_clock.print(buffer.c_str());
8
74
8
75
                buffer.erase();
8
76
8
77
                while(useful_F::go_while){
8
78
                    if(serial_ardu_clock.available()>0)
4
79
                    {
4
80
                        buffer += serial_ardu_clock.read();
4
81
                        buffer += serial_ardu_clock.read();
4
82
                        serial_ardu_clock.flush();
4
83
                        break;
4
84
                    }
8
85
                    else
4
86
                    {
4
87
                        puts("w buforze serial_ardu_clock nie ma avaiable ");
4
88
4
89
                        useful_F::myStaticData->myEventHandler.run("RS232")
4
90
                                ->addEvent("w buforze serial_ardu_clock nie ma avaiable ");
4
91
                        break;
4
92
                    }
8
93
                }
8
94
#ifdef BT_TEST
8
95
                useful_F::go_while = false;
8
96
                return;
8
97
#endif
8
98
            }
4
99
            else if(data_rs232->pointer.ptr_who[0] == iDomConst::FREE)
4
100
            {
4
101
                std::string bufor = "";
4
102
                if(serial_ardu.available()>0) {
4
103
20
104
                    while (useful_F::go_while){
20
105
                        // std::cout << "serial_ardu.available(): "<<serial_ardu.available()<<std::endl;
20
106
                        if(serial_ardu.available()>0){
20
107
                            char t = serial_ardu.read();
20
108
                            // std::cout << "t: "<<t<<std::endl;
20
109
                            if(t == ';'){
4
110
                                serial_ardu.flush();
4
111
                                break;
4
112
                            }
16
113
                            else{
16
114
                                bufor.push_back(t);
16
115
                            }
20
116
                        }
20
117
                    }
4
118
                    useful_F::myStaticData->myEventHandler.run("RS232")->addEvent(bufor);
4
119
4
120
                }
4
121
#ifdef BT_TEST
4
122
                useful_F::go_while = false;
4
123
                return;
4
124
#endif
4
125
            }
16
126
16
127
        }
16
128
    }
0
129
    iDOM_THREAD::stop_thread(threadName, useful_F::myStaticData);
0
130
}
131
#endif // RS232_THREAD_H
/home/pi/programowanie/iDom_server_OOP/src/thread_functions/TEST/rs232_thread_BT.cpp
1
#include <gtest/gtest.h>
2
#include "../../iDom_server_OOP.h"
3
#include "../rs232_thread.h"
4
#include "test_data.h"
5
#include "../../../iDom_server_OOP/src/iDomTools/test/iDomTools_fixture.h"
6
7
std::mutex useful_F::mutex_buf;
8
std::mutex useful_F::mutex_who;
9
10
std::string buffer;
11
12
class rs232_thread_fixture : public iDomTOOLS_ClassTest
13
{
14
15
};
16
17
TEST_F(rs232_thread_fixture, send_Recieve_rs232_thread_fixture_clock)
4
18
{
4
19
    useful_F::go_while = true;
4
20
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 0);
4
21
    thread_data_rs232 test_data_rs232;
4
22
    test_data_rs232.BaudRate = "9600";
4
23
    test_data_rs232.portRS232 = "test_port";
4
24
    test_data_rs232.portRS232_clock = "test_port_clock";
4
25
    unsigned int wh[2];
4
26
    test_data_rs232.pointer.ptr_who = wh;
4
27
    test_data_rs232.pointer.ptr_who[0] = iDomConst::CLOCK;
4
28
    test_data_rs232.pointer.ptr_who[1] = iDomConst::FREE;
4
29
    EXPECT_EQ(test_data_rs232.pointer.ptr_who[1], iDomConst::FREE);
4
30
4
31
    SerialPi_set_recv_msg("OK");
4
32
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"OK");
4
33
    Send_Recieve_rs232_thread(&test_data_rs232,"RS232_THREAD");
4
34
4
35
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"");
4
36
    EXPECT_EQ(test_data_rs232.pointer.ptr_who[1], iDomConst::CLOCK);
4
37
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 0);
4
38
}
39
40
TEST_F(rs232_thread_fixture, send_Recieve_rs232_thread_clock_empty_answer)
4
41
{
4
42
    useful_F::go_while = true;
4
43
    thread_data_rs232 test_data_rs232;
4
44
    test_data_rs232.BaudRate = "9600";
4
45
    test_data_rs232.portRS232 = "test_port";
4
46
    test_data_rs232.portRS232_clock = "test_port_clock";
4
47
    unsigned int test_who[2] = {iDomConst::CLOCK, iDomConst::FREE};
4
48
    EXPECT_EQ(test_who[1], iDomConst::FREE);
4
49
    test_data_rs232.pointer.ptr_who = test_who;
4
50
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 0);
4
51
    SerialPi_set_recv_msg("");
4
52
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"");
4
53
    Send_Recieve_rs232_thread(&test_data_rs232, "RS232_thread");
4
54
4
55
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"");
4
56
    EXPECT_EQ(test_data_rs232.pointer.ptr_who[1], iDomConst::CLOCK);
4
57
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 1);
4
58
}
59
60
TEST_F(rs232_thread_fixture, send_Recieve_rs232_thread_RS232)
4
61
{
4
62
    useful_F::go_while = true;
4
63
    thread_data_rs232 test_data_rs232;
4
64
    test_data_rs232.BaudRate = "9600";
4
65
    test_data_rs232.portRS232 = "test_port";
4
66
    test_data_rs232.portRS232_clock = "test_port_clock";
4
67
    unsigned int test_who[2] = {iDomConst::RS232, iDomConst::FREE};
4
68
    test_data_rs232.pointer.ptr_who = test_who;
4
69
4
70
    test_data_rs232.pointer.ptr_who[0] = iDomConst::RS232;
4
71
    EXPECT_EQ(test_who[0], iDomConst::RS232);
4
72
    SerialPi_set_recv_msg("OK;");
4
73
    Send_Recieve_rs232_thread(&test_data_rs232,"RS232_thread");
4
74
4
75
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"");
4
76
    EXPECT_EQ(test_who[1], iDomConst::RS232);
4
77
}
78
79
TEST_F(rs232_thread_fixture, send_Recieve_rs232_thread_FREE)
4
80
{
4
81
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 0);
4
82
    useful_F::go_while = true;
4
83
    thread_data_rs232 test_data_rs232;
4
84
    test_data_rs232.BaudRate = "9600";
4
85
    test_data_rs232.portRS232 = "test_port";
4
86
    test_data_rs232.portRS232_clock = "test_port_clock";
4
87
    unsigned int test_who[2] = {iDomConst::FREE, iDomConst::FREE};
4
88
    test_data_rs232.pointer.ptr_who = test_who;
4
89
4
90
    test_data_rs232.pointer.ptr_who[0] = iDomConst::FREE;
4
91
    EXPECT_EQ(test_who[0], iDomConst::FREE);
4
92
    SerialPi_set_recv_msg("TEST;");
4
93
    Send_Recieve_rs232_thread(&test_data_rs232,"RS232_thread");
4
94
4
95
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"");
4
96
    EXPECT_EQ(test_who[1], iDomConst::FREE);
4
97
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 1);
4
98
}
/home/pi/programowanie/iDom_server_OOP/src/thread_functions/iDom_thread.cpp
1
#include "iDom_thread.h"
2
#include "../functions/functions.h"
3
#include <tuple>
4
#include <array>
5
#include <functional>
6
7
std::string iDOM_THREAD::start_thread(const std::string& name,
8
                                      std::function<void(thread_data*,const std::string& threadName)> functionToThread, //void(fn)(thread_data),
9
                                      thread_data* my_data,
10
                                      int thread_socket)
16
11
{
16
12
    int freeSlotID = useful_F::findFreeThreadSlot(my_data->main_THREAD_arr);
16
13
16
14
    if ( freeSlotID != -1)
12
15
    {
12
16
        my_data->main_THREAD_arr->at(freeSlotID).thread = std::thread(functionToThread ,my_data, name);
12
17
12
18
        my_data->main_THREAD_arr->at(freeSlotID).thread_name   = name;
12
19
        my_data->main_THREAD_arr->at(freeSlotID).thread_ID     = my_data->main_THREAD_arr->at(freeSlotID).thread.get_id();
12
20
        my_data->main_THREAD_arr->at(freeSlotID).thread_socket = thread_socket;
12
21
        my_data->main_THREAD_arr->at(freeSlotID).thread.detach();
12
22
12
23
        log_file_mutex.mutex_lock();
12
24
        log_file_cout << INFO << "watek " << name << " wystartowal "<< my_data->main_THREAD_arr->at(freeSlotID).thread_ID << std::endl;
12
25
        log_file_mutex.mutex_unlock();
12
26
12
27
        return "DONE - " + name + " STARTED";
12
28
    }
4
29
    return "not free space to new thread";
16
30
}
31
32
std::string iDOM_THREAD::start_thread_RS232(const std::string &name,
33
                                            std::function<void (thread_data_rs232 *, const std::string &)> functionToThread,
34
                                            thread_data* my_data,
35
                                            thread_data_rs232 *my_data_rs232,
36
                                            int thread_socket)
0
37
{
0
38
    int freeSlotID = useful_F::findFreeThreadSlot(my_data->main_THREAD_arr);
0
39
0
40
    if ( freeSlotID != -1)
0
41
    {
0
42
        my_data->main_THREAD_arr->at(freeSlotID).thread = std::thread(functionToThread ,my_data_rs232, name);
0
43
0
44
        my_data->main_THREAD_arr->at(freeSlotID).thread_name   = name;
0
45
        my_data->main_THREAD_arr->at(freeSlotID).thread_ID     = my_data->main_THREAD_arr->at(freeSlotID).thread.get_id();
0
46
        my_data->main_THREAD_arr->at(freeSlotID).thread_socket = thread_socket;
0
47
        my_data->main_THREAD_arr->at(freeSlotID).thread.detach();
0
48
0
49
        log_file_mutex.mutex_lock();
0
50
        log_file_cout << INFO << "watek " << name << " wystartowal "<< my_data->main_THREAD_arr->at(freeSlotID).thread_ID << std::endl;
0
51
        log_file_mutex.mutex_unlock();
0
52
0
53
        return "DONE - " + name + " STARTED";
0
54
    }
0
55
    return "not free space to new thread";
0
56
}
57
58
void iDOM_THREAD::stop_thread(const std::string& name,
59
                              thread_data* my_data)
16
60
{
16
61
    try
16
62
    {
92
63
        for (int i =0; i< iDomConst::MAX_CONNECTION; ++i)
88
64
        {
88
65
            if (my_data->main_THREAD_arr->at(i).thread_ID == std::this_thread::get_id())
12
66
            {
12
67
                //my_data->main_THREAD_arr[i].thread.detach();
12
68
                my_data->main_THREAD_arr->at(i).thread_name ="  -empty-  ";
12
69
                my_data->main_THREAD_arr->at(i).thread_ID = std::thread::id();
12
70
                my_data->main_THREAD_arr->at(i).thread_socket = 0;
12
71
                break;
12
72
            }
88
73
        }
16
74
    }
16
75
    catch (std::system_error &e)
0
76
    {
0
77
        log_file_mutex.mutex_lock();
0
78
        log_file_cout << ERROR<< "zlapano wyjatek w watku: " << name << ": " << e.what()<< std::endl;
0
79
        log_file_mutex.mutex_unlock();
0
80
    }
16
81
16
82
    log_file_mutex.mutex_lock();
16
83
    log_file_cout << INFO<< "koniec watku: " <<name << std::endl;
16
84
    log_file_mutex.mutex_unlock();
16
85
}
86
87
void iDOM_THREAD::waitUntilAllThreadEnd(thread_data *my_data)
0
88
{
0
89
    int threadCounter = 0;
0
90
    int counter = 20;
0
91
    do{
0
92
        if (--counter == 0){
0
93
            puts("niedoczekalem sie konca watkow");
0
94
            break;
0
95
        }
0
96
        std::this_thread::sleep_for(std::chrono::milliseconds(1500));
0
97
        threadCounter = 0;
0
98
        for(auto i = my_data->main_THREAD_arr->begin(); i < my_data->main_THREAD_arr->end(); ++i)
0
99
        {
0
100
            threadCounter += i->thread_socket;
0
101
            if (i->thread_socket != 0)
0
102
                std::cout << "thread name: "<< i->thread_name << std::endl;
0
103
        }
0
104
        std::cout << "watki pracuja "<<threadCounter<< std::endl;
0
105
    } while(threadCounter != 0);
0
106
}
107
/home/pi/programowanie/iDom_server_OOP/test/iDom_TESTs-CMAKE/../../libs/json/single_include/nlohmann/../../../../src/functions/../blockQueue/../logger/logger.hpp
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
6
84
    {
6
85
        *static_cast<std::ostringstream *>(this) << t;
6
86
        return (*this);
6
87
    }
_ZN6LoggerlsIA45_cEERS_RKT_
5
84
    {
5
85
        *static_cast<std::ostringstream *>(this) << t;
5
86
        return (*this);
5
87
    }
_ZN6LoggerlsIA10_cEERS_RKT_
1
84
    {
1
85
        *static_cast<std::ostringstream *>(this) << t;
1
86
        return (*this);
1
87
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
282
107
{
282
108
    out.put('\n');
282
109
    out.flush();
282
110
    return (out);
282
111
}
112
}// end namespace std
113
114
#endif
/home/pi/programowanie/iDom_server_OOP/test/iDom_TESTs-CMAKE/../../libs/json/single_include/nlohmann/../../../../src/functions/../c_connection/../iDom_server_OOP.h
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
2
41
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    RADIO_EQ_CONTAINER *main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/home/pi/programowanie/iDom_server_OOP/test/iDom_TESTs-CMAKE/../../libs/json/single_include/nlohmann/json.hpp
1
/*
2
    __ _____ _____ _____
3
 __|  |   __|     |   | |  JSON for Modern C++
4
|  |  |__   |  |  | | | |  version 3.2.0
5
|_____|_____|_____|_|___|  https://github.com/nlohmann/json
6
7
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8
SPDX-License-Identifier: MIT
9
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
10
11
Permission is hereby  granted, free of charge, to any  person obtaining a copy
12
of this software and associated  documentation files (the "Software"), to deal
13
in the Software  without restriction, including without  limitation the rights
14
to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
15
copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
16
furnished to do so, subject to the following conditions:
17
18
The above copyright notice and this permission notice shall be included in all
19
copies or substantial portions of the Software.
20
21
THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
22
IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
23
FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
24
AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
25
LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
27
SOFTWARE.
28
*/
29
30
#ifndef NLOHMANN_JSON_HPP
31
#define NLOHMANN_JSON_HPP
32
33
#define NLOHMANN_JSON_VERSION_MAJOR 3
34
#define NLOHMANN_JSON_VERSION_MINOR 2
35
#define NLOHMANN_JSON_VERSION_PATCH 0
36
37
#include <algorithm> // all_of, find, for_each
38
#include <cassert> // assert
39
#include <ciso646> // and, not, or
40
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
41
#include <functional> // hash, less
42
#include <initializer_list> // initializer_list
43
#include <iosfwd> // istream, ostream
44
#include <iterator> // iterator_traits, random_access_iterator_tag
45
#include <numeric> // accumulate
46
#include <string> // string, stoi, to_string
47
#include <utility> // declval, forward, move, pair, swap
48
49
// #include <nlohmann/json_fwd.hpp>
50
#ifndef NLOHMANN_JSON_FWD_HPP
51
#define NLOHMANN_JSON_FWD_HPP
52
53
#include <cstdint> // int64_t, uint64_t
54
#include <map> // map
55
#include <memory> // allocator
56
#include <string> // string
57
#include <vector> // vector
58
59
/*!
60
@brief namespace for Niels Lohmann
61
@see https://github.com/nlohmann
62
@since version 1.0.0
63
*/
64
namespace nlohmann
65
{
66
/*!
67
@brief default JSONSerializer template argument
68
69
This serializer ignores the template arguments and uses ADL
70
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
71
for serialization.
72
*/
73
template<typename T = void, typename SFINAE = void>
74
struct adl_serializer;
75
76
template<template<typename U, typename V, typename... Args> class ObjectType =
77
         std::map,
78
         template<typename U, typename... Args> class ArrayType = std::vector,
79
         class StringType = std::string, class BooleanType = bool,
80
         class NumberIntegerType = std::int64_t,
81
         class NumberUnsignedType = std::uint64_t,
82
         class NumberFloatType = double,
83
         template<typename U> class AllocatorType = std::allocator,
84
         template<typename T, typename SFINAE = void> class JSONSerializer =
85
         adl_serializer>
86
class basic_json;
87
88
/*!
89
@brief JSON Pointer
90
91
A JSON pointer defines a string syntax for identifying a specific value
92
within a JSON document. It can be used with functions `at` and
93
`operator[]`. Furthermore, JSON pointers are the base for JSON patches.
94
95
@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
96
97
@since version 2.0.0
98
*/
99
template<typename BasicJsonType>
100
class json_pointer;
101
102
/*!
103
@brief default JSON class
104
105
This type is the default specialization of the @ref basic_json class which
106
uses the standard template types.
107
108
@since version 1.0.0
109
*/
110
using json = basic_json<>;
111
}
112
113
#endif
114
115
// #include <nlohmann/detail/macro_scope.hpp>
116
117
118
// This file contains all internal macro definitions
119
// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
120
121
// exclude unsupported compilers
122
#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
123
    #if defined(__clang__)
124
        #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
125
            #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
126
        #endif
127
    #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
128
        #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900
129
            #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
130
        #endif
131
    #endif
132
#endif
133
134
// disable float-equal warnings on GCC/clang
135
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
136
    #pragma GCC diagnostic push
137
    #pragma GCC diagnostic ignored "-Wfloat-equal"
138
#endif
139
140
// disable documentation warnings on clang
141
#if defined(__clang__)
142
    #pragma GCC diagnostic push
143
    #pragma GCC diagnostic ignored "-Wdocumentation"
144
#endif
145
146
// allow for portable deprecation warnings
147
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
148
    #define JSON_DEPRECATED __attribute__((deprecated))
149
#elif defined(_MSC_VER)
150
    #define JSON_DEPRECATED __declspec(deprecated)
151
#else
152
    #define JSON_DEPRECATED
153
#endif
154
155
// allow to disable exceptions
156
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
612
157
    #define JSON_THROW(exception) throw exception
35.2k
158
    #define JSON_TRY try
159
    #define JSON_CATCH(exception) catch(exception)
160
    #define JSON_INTERNAL_CATCH(exception) catch(exception)
161
#else
162
    #define JSON_THROW(exception) std::abort()
163
    #define JSON_TRY if(true)
164
    #define JSON_CATCH(exception) if(false)
165
    #define JSON_INTERNAL_CATCH(exception) if(false)
166
#endif
167
168
// override exception macros
169
#if defined(JSON_THROW_USER)
170
    #undef JSON_THROW
171
    #define JSON_THROW JSON_THROW_USER
172
#endif
173
#if defined(JSON_TRY_USER)
174
    #undef JSON_TRY
175
    #define JSON_TRY JSON_TRY_USER
176
#endif
177
#if defined(JSON_CATCH_USER)
178
    #undef JSON_CATCH
179
    #define JSON_CATCH JSON_CATCH_USER
180
    #undef JSON_INTERNAL_CATCH
181
    #define JSON_INTERNAL_CATCH JSON_CATCH_USER
182
#endif
183
#if defined(JSON_INTERNAL_CATCH_USER)
184
    #undef JSON_INTERNAL_CATCH
185
    #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
186
#endif
187
188
// manual branch prediction
189
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
24.9M
190
    #define JSON_LIKELY(x)      __builtin_expect(!!(x), 1)
3.24M
191
    #define JSON_UNLIKELY(x)    __builtin_expect(!!(x), 0)
192
#else
193
    #define JSON_LIKELY(x)      x
194
    #define JSON_UNLIKELY(x)    x
195
#endif
196
197
// C++ language standard detection
198
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
199
    #define JSON_HAS_CPP_17
200
    #define JSON_HAS_CPP_14
201
#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
202
    #define JSON_HAS_CPP_14
203
#endif
204
205
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
206
// may be removed in the future once the class is split.
207
208
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION                                \
209
    template<template<typename, typename, typename...> class ObjectType,   \
210
             template<typename, typename...> class ArrayType,              \
211
             class StringType, class BooleanType, class NumberIntegerType, \
212
             class NumberUnsignedType, class NumberFloatType,              \
213
             template<typename> class AllocatorType,                       \
214
             template<typename, typename = void> class JSONSerializer>
215
216
#define NLOHMANN_BASIC_JSON_TPL                                            \
217
    basic_json<ObjectType, ArrayType, StringType, BooleanType,             \
218
    NumberIntegerType, NumberUnsignedType, NumberFloatType,                \
219
    AllocatorType, JSONSerializer>
220
221
// #include <nlohmann/detail/meta/cpp_future.hpp>
222
223
224
#include <ciso646> // not
225
#include <cstddef> // size_t
226
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
227
228
namespace nlohmann
229
{
230
namespace detail
231
{
232
// alias templates to reduce boilerplate
233
template<bool B, typename T = void>
234
using enable_if_t = typename std::enable_if<B, T>::type;
235
236
template<typename T>
237
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
238
239
// implementation of C++14 index_sequence and affiliates
240
// source: https://stackoverflow.com/a/32223343
241
template<std::size_t... Ints>
242
struct index_sequence
243
{
244
    using type = index_sequence;
245
    using value_type = std::size_t;
246
    static constexpr std::size_t size() noexcept
247
    {
248
        return sizeof...(Ints);
249
    }
250
};
251
252
template<class Sequence1, class Sequence2>
253
struct merge_and_renumber;
254
255
template<std::size_t... I1, std::size_t... I2>
256
struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
257
        : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
258
259
template<std::size_t N>
260
struct make_index_sequence
261
    : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
262
      typename make_index_sequence < N - N / 2 >::type > {};
263
264
template<> struct make_index_sequence<0> : index_sequence<> {};
265
template<> struct make_index_sequence<1> : index_sequence<0> {};
266
267
template<typename... Ts>
268
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
269
270
// dispatch utility (taken from ranges-v3)
271
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
272
template<> struct priority_tag<0> {};
273
274
// taken from ranges-v3
275
template<typename T>
276
struct static_const
277
{
278
    static constexpr T value{};
279
};
280
281
template<typename T>
282
constexpr T static_const<T>::value;
283
}
284
}
285
286
// #include <nlohmann/detail/meta/type_traits.hpp>
287
288
289
#include <ciso646> // not
290
#include <limits> // numeric_limits
291
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
292
#include <utility> // declval
293
294
// #include <nlohmann/json_fwd.hpp>
295
296
// #include <nlohmann/detail/meta/cpp_future.hpp>
297
298
// #include <nlohmann/detail/meta/detected.hpp>
299
300
301
#include <type_traits>
302
303
// #include <nlohmann/detail/meta/void_t.hpp>
304
305
306
namespace nlohmann
307
{
308
namespace detail
309
{
310
template <typename ...Ts> struct make_void
311
{
312
    using type = void;
313
};
314
template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
315
}
316
}
317
318
319
// http://en.cppreference.com/w/cpp/experimental/is_detected
320
namespace nlohmann
321
{
322
namespace detail
323
{
324
struct nonesuch
325
{
326
    nonesuch() = delete;
327
    ~nonesuch() = delete;
328
    nonesuch(nonesuch const&) = delete;
329
    void operator=(nonesuch const&) = delete;
330
};
331
332
template <class Default,
333
          class AlwaysVoid,
334
          template <class...> class Op,
335
          class... Args>
336
struct detector
337
{
338
    using value_t = std::false_type;
339
    using type = Default;
340
};
341
342
template <class Default, template <class...> class Op, class... Args>
343
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
344
{
345
    using value_t = std::true_type;
346
    using type = Op<Args...>;
347
};
348
349
template <template <class...> class Op, class... Args>
350
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
351
352
template <template <class...> class Op, class... Args>
353
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
354
355
template <class Default, template <class...> class Op, class... Args>
356
using detected_or = detector<Default, void, Op, Args...>;
357
358
template <class Default, template <class...> class Op, class... Args>
359
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
360
361
template <class Expected, template <class...> class Op, class... Args>
362
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
363
364
template <class To, template <class...> class Op, class... Args>
365
using is_detected_convertible =
366
    std::is_convertible<detected_t<Op, Args...>, To>;
367
}
368
}
369
370
// #include <nlohmann/detail/macro_scope.hpp>
371
372
373
namespace nlohmann
374
{
375
/*!
376
@brief detail namespace with internal helper functions
377
378
This namespace collects functions that should not be exposed,
379
implementations of some @ref basic_json methods, and meta-programming helpers.
380
381
@since version 2.1.0
382
*/
383
namespace detail
384
{
385
/////////////
386
// helpers //
387
/////////////
388
389
template<typename> struct is_basic_json : std::false_type {};
390
391
NLOHMANN_BASIC_JSON_TPL_DECLARATION
392
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
393
394
//////////////////////////
395
// aliases for detected //
396
//////////////////////////
397
398
template <typename T>
399
using mapped_type_t = typename T::mapped_type;
400
401
template <typename T>
402
using key_type_t = typename T::key_type;
403
404
template <typename T>
405
using value_type_t = typename T::value_type;
406
407
template <typename T>
408
using difference_type_t = typename T::difference_type;
409
410
template <typename T>
411
using pointer_t = typename T::pointer;
412
413
template <typename T>
414
using reference_t = typename T::reference;
415
416
template <typename T>
417
using iterator_category_t = typename T::iterator_category;
418
419
template <typename T>
420
using iterator_t = typename T::iterator;
421
422
template <typename T, typename... Args>
423
using to_json_function = decltype(T::to_json(std::declval<Args>()...));
424
425
template <typename T, typename... Args>
426
using from_json_function = decltype(T::from_json(std::declval<Args>()...));
427
428
///////////////////
429
// is_ functions //
430
///////////////////
431
432
template <typename T, typename = void>
433
struct is_iterator_traits : std::false_type {};
434
435
template <typename T>
436
struct is_iterator_traits<std::iterator_traits<T>>
437
{
438
  private:
439
    using traits = std::iterator_traits<T>;
440
441
  public:
442
    static constexpr auto value =
443
        is_detected<value_type_t, traits>::value &&
444
        is_detected<difference_type_t, traits>::value &&
445
        is_detected<pointer_t, traits>::value &&
446
        is_detected<iterator_category_t, traits>::value &&
447
        is_detected<reference_t, traits>::value;
448
};
449
450
// source: https://stackoverflow.com/a/37193089/4116453
451
452
template <typename T, typename = void>
453
struct is_complete_type : std::false_type {};
454
455
template <typename T>
456
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
457
458
template <typename BasicJsonType, typename CompatibleObjectType,
459
          typename = void>
460
struct is_compatible_object_type_impl : std::false_type {};
461
462
template <typename BasicJsonType, typename CompatibleObjectType>
463
struct is_compatible_object_type_impl <
464
    BasicJsonType, CompatibleObjectType,
465
    enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value and
466
    is_detected<key_type_t, CompatibleObjectType>::value >>
467
{
468
469
    using object_t = typename BasicJsonType::object_t;
470
471
    // macOS's is_constructible does not play well with nonesuch...
472
    static constexpr bool value =
473
        std::is_constructible<typename object_t::key_type,
474
        typename CompatibleObjectType::key_type>::value and
475
        std::is_constructible<typename object_t::mapped_type,
476
        typename CompatibleObjectType::mapped_type>::value;
477
};
478
479
template <typename BasicJsonType, typename CompatibleObjectType>
480
struct is_compatible_object_type
481
    : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
482
483
template <typename BasicJsonType, typename CompatibleStringType,
484
          typename = void>
485
struct is_compatible_string_type_impl : std::false_type {};
486
487
template <typename BasicJsonType, typename CompatibleStringType>
488
struct is_compatible_string_type_impl <
489
    BasicJsonType, CompatibleStringType,
490
    enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
491
    value_type_t, CompatibleStringType>::value >>
492
{
493
    static constexpr auto value =
494
        std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
495
};
496
497
template <typename BasicJsonType, typename CompatibleStringType>
498
struct is_compatible_string_type
499
    : is_compatible_string_type_impl<BasicJsonType, CompatibleStringType> {};
500
501
template <typename BasicJsonType, typename CompatibleArrayType, typename = void>
502
struct is_compatible_array_type_impl : std::false_type {};
503
504
template <typename BasicJsonType, typename CompatibleArrayType>
505
struct is_compatible_array_type_impl <
506
    BasicJsonType, CompatibleArrayType,
507
    enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and
508
    is_detected<iterator_t, CompatibleArrayType>::value >>
509
{
510
    // This is needed because json_reverse_iterator has a ::iterator type...
511
    // Therefore it is detected as a CompatibleArrayType.
512
    // The real fix would be to have an Iterable concept.
513
    static constexpr bool value = not is_iterator_traits<std::iterator_traits<CompatibleArrayType>>::value;
514
};
515
516
template <typename BasicJsonType, typename CompatibleArrayType>
517
struct is_compatible_array_type
518
    : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
519
520
template <typename RealIntegerType, typename CompatibleNumberIntegerType,
521
          typename = void>
522
struct is_compatible_integer_type_impl : std::false_type {};
523
524
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
525
struct is_compatible_integer_type_impl <
526
    RealIntegerType, CompatibleNumberIntegerType,
527
    enable_if_t<std::is_integral<RealIntegerType>::value and
528
    std::is_integral<CompatibleNumberIntegerType>::value and
529
    not std::is_same<bool, CompatibleNumberIntegerType>::value >>
530
{
531
    // is there an assert somewhere on overflows?
532
    using RealLimits = std::numeric_limits<RealIntegerType>;
533
    using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
534
535
    static constexpr auto value =
536
        std::is_constructible<RealIntegerType,
537
        CompatibleNumberIntegerType>::value and
538
        CompatibleLimits::is_integer and
539
        RealLimits::is_signed == CompatibleLimits::is_signed;
540
};
541
542
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
543
struct is_compatible_integer_type
544
    : is_compatible_integer_type_impl<RealIntegerType,
545
      CompatibleNumberIntegerType> {};
546
547
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
548
template<typename BasicJsonType, typename T>
549
struct has_from_json
550
{
551
    using serializer = typename BasicJsonType::template json_serializer<T, void>;
552
553
    static constexpr bool value =
554
        is_detected_exact<void, from_json_function, serializer,
555
        const BasicJsonType&, T&>::value;
556
};
557
558
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
559
// this overload is used for non-default-constructible user-defined-types
560
template<typename BasicJsonType, typename T>
561
struct has_non_default_from_json
562
{
563
    using serializer = typename BasicJsonType::template json_serializer<T, void>;
564
565
    static constexpr bool value =
566
        is_detected_exact<T, from_json_function, serializer,
567
        const BasicJsonType&>::value;
568
};
569
570
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
571
template<typename BasicJsonType, typename T>
572
struct has_to_json
573
{
574
    using serializer = typename BasicJsonType::template json_serializer<T, void>;
575
576
    static constexpr bool value =
577
        is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
578
        T>::value;
579
};
580
581
template <typename BasicJsonType, typename CompatibleType, typename = void>
582
struct is_compatible_type_impl: std::false_type {};
583
584
template <typename BasicJsonType, typename CompatibleType>
585
struct is_compatible_type_impl <
586
    BasicJsonType, CompatibleType,
587
    enable_if_t<is_complete_type<CompatibleType>::value >>
588
{
589
    static constexpr bool value =
590
        has_to_json<BasicJsonType, CompatibleType>::value;
591
};
592
593
template <typename BasicJsonType, typename CompatibleType>
594
struct is_compatible_type
595
    : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
596
}
597
}
598
599
// #include <nlohmann/detail/exceptions.hpp>
600
601
602
#include <exception> // exception
603
#include <stdexcept> // runtime_error
604
#include <string> // to_string
605
606
namespace nlohmann
607
{
608
namespace detail
609
{
610
////////////////
611
// exceptions //
612
////////////////
613
614
/*!
615
@brief general exception of the @ref basic_json class
616
617
This class is an extension of `std::exception` objects with a member @a id for
618
exception ids. It is used as the base class for all exceptions thrown by the
619
@ref basic_json class. This class can hence be used as "wildcard" to catch
620
exceptions.
621
622
Subclasses:
623
- @ref parse_error for exceptions indicating a parse error
624
- @ref invalid_iterator for exceptions indicating errors with iterators
625
- @ref type_error for exceptions indicating executing a member function with
626
                  a wrong type
627
- @ref out_of_range for exceptions indicating access out of the defined range
628
- @ref other_error for exceptions indicating other library errors
629
630
@internal
631
@note To have nothrow-copy-constructible exceptions, we internally use
632
      `std::runtime_error` which can cope with arbitrary-length error messages.
633
      Intermediate strings are built with static functions and then passed to
634
      the actual constructor.
635
@endinternal
636
637
@liveexample{The following code shows how arbitrary library exceptions can be
638
caught.,exception}
639
640
@since version 3.0.0
641
*/
642
class exception : public std::exception
643
{
644
  public:
645
    /// returns the explanatory string
646
    const char* what() const noexcept override
0
647
    {
0
648
        return m.what();
0
649
    }
650
651
    /// the id of the exception
652
    const int id;
653
654
  protected:
4
655
    exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
656
657
    static std::string name(const std::string& ename, int id_)
4
658
    {
4
659
        return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
4
660
    }
661
662
  private:
663
    /// an exception object as storage for error messages
664
    std::runtime_error m;
665
};
666
667
/*!
668
@brief exception indicating a parse error
669
670
This exception is thrown by the library when a parse error occurs. Parse errors
671
can occur during the deserialization of JSON text, CBOR, MessagePack, as well
672
as when using JSON Patch.
673
674
Member @a byte holds the byte index of the last read character in the input
675
file.
676
677
Exceptions have ids 1xx.
678
679
name / id                      | example message | description
680
------------------------------ | --------------- | -------------------------
681
json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.
682
json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
683
json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.
684
json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects.
685
json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
686
json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`.
687
json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.
688
json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
689
json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.
690
json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.
691
json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
692
json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
693
694
@note For an input with n bytes, 1 is the index of the first character and n+1
695
      is the index of the terminating null byte or the end of file. This also
696
      holds true when reading a byte vector (CBOR or MessagePack).
697
698
@liveexample{The following code shows how a `parse_error` exception can be
699
caught.,parse_error}
700
701
@sa @ref exception for the base class of the library exceptions
702
@sa @ref invalid_iterator for exceptions indicating errors with iterators
703
@sa @ref type_error for exceptions indicating executing a member function with
704
                    a wrong type
705
@sa @ref out_of_range for exceptions indicating access out of the defined range
706
@sa @ref other_error for exceptions indicating other library errors
707
708
@since version 3.0.0
709
*/
710
class parse_error : public exception
711
{
712
  public:
713
    /*!
714
    @brief create a parse error exception
715
    @param[in] id_       the id of the exception
716
    @param[in] byte_     the byte index where the error occurred (or 0 if the
717
                         position cannot be determined)
718
    @param[in] what_arg  the explanatory string
719
    @return parse_error object
720
    */
721
    static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
0
722
    {
0
723
        std::string w = exception::name("parse_error", id_) + "parse error" +
0
724
                        (byte_ != 0 ? (" at " + std::to_string(byte_)) : "") +
0
725
                        ": " + what_arg;
0
726
        return parse_error(id_, byte_, w.c_str());
0
727
    }
728
729
    /*!
730
    @brief byte index of the parse error
731
732
    The byte index of the last read character in the input file.
733
734
    @note For an input with n bytes, 1 is the index of the first character and
735
          n+1 is the index of the terminating null byte or the end of file.
736
          This also holds true when reading a byte vector (CBOR or MessagePack).
737
    */
738
    const std::size_t byte;
739
740
  private:
741
    parse_error(int id_, std::size_t byte_, const char* what_arg)
0
742
        : exception(id_, what_arg), byte(byte_) {}
743
};
744
745
/*!
746
@brief exception indicating errors with iterators
747
748
This exception is thrown if iterators passed to a library function do not match
749
the expected semantics.
750
751
Exceptions have ids 2xx.
752
753
name / id                           | example message | description
754
----------------------------------- | --------------- | -------------------------
755
json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
756
json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
757
json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
758
json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.
759
json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
760
json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.
761
json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.
762
json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
763
json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
764
json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
765
json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to.
766
json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.
767
json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.
768
json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().
769
770
@liveexample{The following code shows how an `invalid_iterator` exception can be
771
caught.,invalid_iterator}
772
773
@sa @ref exception for the base class of the library exceptions
774
@sa @ref parse_error for exceptions indicating a parse error
775
@sa @ref type_error for exceptions indicating executing a member function with
776
                    a wrong type
777
@sa @ref out_of_range for exceptions indicating access out of the defined range
778
@sa @ref other_error for exceptions indicating other library errors
779
780
@since version 3.0.0
781
*/
782
class invalid_iterator : public exception
783
{
784
  public:
785
    static invalid_iterator create(int id_, const std::string& what_arg)
0
786
    {
0
787
        std::string w = exception::name("invalid_iterator", id_) + what_arg;
0
788
        return invalid_iterator(id_, w.c_str());
0
789
    }
790
791
  private:
792
    invalid_iterator(int id_, const char* what_arg)
0
793
        : exception(id_, what_arg) {}
794
};
795
796
/*!
797
@brief exception indicating executing a member function with a wrong type
798
799
This exception is thrown in case of a type error; that is, a library function is
800
executed on a JSON value whose type does not match the expected semantics.
801
802
Exceptions have ids 3xx.
803
804
name / id                     | example message | description
805
----------------------------- | --------------- | -------------------------
806
json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
807
json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
808
json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&.
809
json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
810
json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
811
json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
812
json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.
813
json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.
814
json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.
815
json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.
816
json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.
817
json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.
818
json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
819
json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.
820
json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.
821
json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. |
822
823
@liveexample{The following code shows how a `type_error` exception can be
824
caught.,type_error}
825
826
@sa @ref exception for the base class of the library exceptions
827
@sa @ref parse_error for exceptions indicating a parse error
828
@sa @ref invalid_iterator for exceptions indicating errors with iterators
829
@sa @ref out_of_range for exceptions indicating access out of the defined range
830
@sa @ref other_error for exceptions indicating other library errors
831
832
@since version 3.0.0
833
*/
834
class type_error : public exception
835
{
836
  public:
837
    static type_error create(int id_, const std::string& what_arg)
0
838
    {
0
839
        std::string w = exception::name("type_error", id_) + what_arg;
0
840
        return type_error(id_, w.c_str());
0
841
    }
842
843
  private:
0
844
    type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
845
};
846
847
/*!
848
@brief exception indicating access out of the defined range
849
850
This exception is thrown in case a library function is called on an input
851
parameter that exceeds the expected range, for instance in case of array
852
indices or nonexisting object keys.
853
854
Exceptions have ids 4xx.
855
856
name / id                       | example message | description
857
------------------------------- | --------------- | -------------------------
858
json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.
859
json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.
860
json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.
861
json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
862
json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
863
json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
864
json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON only supports integers numbers up to 9223372036854775807. |
865
json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
866
867
@liveexample{The following code shows how an `out_of_range` exception can be
868
caught.,out_of_range}
869
870
@sa @ref exception for the base class of the library exceptions
871
@sa @ref parse_error for exceptions indicating a parse error
872
@sa @ref invalid_iterator for exceptions indicating errors with iterators
873
@sa @ref type_error for exceptions indicating executing a member function with
874
                    a wrong type
875
@sa @ref other_error for exceptions indicating other library errors
876
877
@since version 3.0.0
878
*/
879
class out_of_range : public exception
880
{
881
  public:
882
    static out_of_range create(int id_, const std::string& what_arg)
4
883
    {
4
884
        std::string w = exception::name("out_of_range", id_) + what_arg;
4
885
        return out_of_range(id_, w.c_str());
4
886
    }
887
888
  private:
4
889
    out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
890
};
891
892
/*!
893
@brief exception indicating other library errors
894
895
This exception is thrown in case of errors that cannot be classified with the
896
other exception types.
897
898
Exceptions have ids 5xx.
899
900
name / id                      | example message | description
901
------------------------------ | --------------- | -------------------------
902
json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
903
904
@sa @ref exception for the base class of the library exceptions
905
@sa @ref parse_error for exceptions indicating a parse error
906
@sa @ref invalid_iterator for exceptions indicating errors with iterators
907
@sa @ref type_error for exceptions indicating executing a member function with
908
                    a wrong type
909
@sa @ref out_of_range for exceptions indicating access out of the defined range
910
911
@liveexample{The following code shows how an `other_error` exception can be
912
caught.,other_error}
913
914
@since version 3.0.0
915
*/
916
class other_error : public exception
917
{
918
  public:
919
    static other_error create(int id_, const std::string& what_arg)
0
920
    {
0
921
        std::string w = exception::name("other_error", id_) + what_arg;
0
922
        return other_error(id_, w.c_str());
0
923
    }
924
925
  private:
0
926
    other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
927
};
928
}
929
}
930
931
// #include <nlohmann/detail/value_t.hpp>
932
933
934
#include <array> // array
935
#include <ciso646> // and
936
#include <cstddef> // size_t
937
#include <cstdint> // uint8_t
938
939
namespace nlohmann
940
{
941
namespace detail
942
{
943
///////////////////////////
944
// JSON type enumeration //
945
///////////////////////////
946
947
/*!
948
@brief the JSON type enumeration
949
950
This enumeration collects the different JSON types. It is internally used to
951
distinguish the stored values, and the functions @ref basic_json::is_null(),
952
@ref basic_json::is_object(), @ref basic_json::is_array(),
953
@ref basic_json::is_string(), @ref basic_json::is_boolean(),
954
@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
955
@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
956
@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
957
@ref basic_json::is_structured() rely on it.
958
959
@note There are three enumeration entries (number_integer, number_unsigned, and
960
number_float), because the library distinguishes these three types for numbers:
961
@ref basic_json::number_unsigned_t is used for unsigned integers,
962
@ref basic_json::number_integer_t is used for signed integers, and
963
@ref basic_json::number_float_t is used for floating-point numbers or to
964
approximate integers which do not fit in the limits of their respective type.
965
966
@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON
967
value with the default value for a given type
968
969
@since version 1.0.0
970
*/
971
enum class value_t : std::uint8_t
972
{
973
    null,             ///< null value
974
    object,           ///< object (unordered set of name/value pairs)
975
    array,            ///< array (ordered collection of values)
976
    string,           ///< string value
977
    boolean,          ///< boolean value
978
    number_integer,   ///< number value (signed integer)
979
    number_unsigned,  ///< number value (unsigned integer)
980
    number_float,     ///< number value (floating-point)
981
    discarded         ///< discarded by the the parser callback function
982
};
983
984
/*!
985
@brief comparison operator for JSON types
986
987
Returns an ordering that is similar to Python:
988
- order: null < boolean < number < object < array < string
989
- furthermore, each type is not smaller than itself
990
- discarded values are not comparable
991
992
@since version 1.0.0
993
*/
994
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
0
995
{
0
996
    static constexpr std::array<std::uint8_t, 8> order = {{
0
997
            0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
0
998
            1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */
0
999
        }
0
1000
    };
0
1001
0
1002
    const auto l_index = static_cast<std::size_t>(lhs);
0
1003
    const auto r_index = static_cast<std::size_t>(rhs);
0
1004
    return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
0
1005
}
1006
}
1007
}
1008
1009
// #include <nlohmann/detail/conversions/from_json.hpp>
1010
1011
1012
#include <algorithm> // transform
1013
#include <array> // array
1014
#include <ciso646> // and, not
1015
#include <forward_list> // forward_list
1016
#include <iterator> // inserter, front_inserter, end
1017
#include <map> // map
1018
#include <string> // string
1019
#include <tuple> // tuple, make_tuple
1020
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
1021
#include <unordered_map> // unordered_map
1022
#include <utility> // pair, declval
1023
#include <valarray> // valarray
1024
1025
// #include <nlohmann/detail/exceptions.hpp>
1026
1027
// #include <nlohmann/detail/macro_scope.hpp>
1028
1029
// #include <nlohmann/detail/meta/cpp_future.hpp>
1030
1031
// #include <nlohmann/detail/meta/type_traits.hpp>
1032
1033
// #include <nlohmann/detail/value_t.hpp>
1034
1035
1036
namespace nlohmann
1037
{
1038
namespace detail
1039
{
1040
template<typename BasicJsonType>
1041
void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
1042
{
1043
    if (JSON_UNLIKELY(not j.is_null()))
1044
    {
1045
        JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
1046
    }
1047
    n = nullptr;
1048
}
1049
1050
// overloads for basic_json template parameters
1051
template<typename BasicJsonType, typename ArithmeticType,
1052
         enable_if_t<std::is_arithmetic<ArithmeticType>::value and
1053
                     not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1054
                     int> = 0>
1055
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
592
1056
{
592
1057
    switch (static_cast<value_t>(j))
592
1058
    {
0
1059
        case value_t::number_unsigned:
0
1060
        {
0
1061
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
0
1062
            break;
0
1063
        }
0
1064
        case value_t::number_integer:
0
1065
        {
0
1066
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
0
1067
            break;
0
1068
        }
592
1069
        case value_t::number_float:
592
1070
        {
592
1071
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
592
1072
            break;
0
1073
        }
0
1074
0
1075
        default:
0
1076
            JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
592
1077
    }
592
1078
}
1079
1080
template<typename BasicJsonType>
1081
void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
8
1082
{
8
1083
    if (JSON_UNLIKELY(not j.is_boolean()))
0
1084
    {
0
1085
        JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
0
1086
    }
8
1087
    b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
8
1088
}
1089
1090
template<typename BasicJsonType>
1091
void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
31.2k
1092
{
31.2k
1093
    if (JSON_UNLIKELY(not j.is_string()))
0
1094
    {
0
1095
        JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
0
1096
    }
31.2k
1097
    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
31.2k
1098
}
1099
1100
template <
1101
    typename BasicJsonType, typename CompatibleStringType,
1102
    enable_if_t <
1103
        is_compatible_string_type<BasicJsonType, CompatibleStringType>::value and
1104
        not std::is_same<typename BasicJsonType::string_t,
1105
                         CompatibleStringType>::value,
1106
        int > = 0 >
1107
void from_json(const BasicJsonType& j, CompatibleStringType& s)
1108
{
1109
    if (JSON_UNLIKELY(not j.is_string()))
1110
    {
1111
        JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
1112
    }
1113
1114
    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
1115
}
1116
1117
template<typename BasicJsonType>
1118
void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
592
1119
{
592
1120
    get_arithmetic_value(j, val);
592
1121
}
1122
1123
template<typename BasicJsonType>
1124
void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
1125
{
1126
    get_arithmetic_value(j, val);
1127
}
1128
1129
template<typename BasicJsonType>
1130
void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
1131
{
1132
    get_arithmetic_value(j, val);
1133
}
1134
1135
template<typename BasicJsonType, typename EnumType,
1136
         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
1137
void from_json(const BasicJsonType& j, EnumType& e)
1138
{
1139
    typename std::underlying_type<EnumType>::type val;
1140
    get_arithmetic_value(j, val);
1141
    e = static_cast<EnumType>(val);
1142
}
1143
1144
// forward_list doesn't have an insert method
1145
template<typename BasicJsonType, typename T, typename Allocator,
1146
         enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1147
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
1148
{
1149
    if (JSON_UNLIKELY(not j.is_array()))
1150
    {
1151
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1152
    }
1153
    std::transform(j.rbegin(), j.rend(),
1154
                   std::front_inserter(l), [](const BasicJsonType & i)
1155
    {
1156
        return i.template get<T>();
1157
    });
1158
}
1159
1160
// valarray doesn't have an insert method
1161
template<typename BasicJsonType, typename T,
1162
         enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1163
void from_json(const BasicJsonType& j, std::valarray<T>& l)
1164
{
1165
    if (JSON_UNLIKELY(not j.is_array()))
1166
    {
1167
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1168
    }
1169
    l.resize(j.size());
1170
    std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
1171
}
1172
1173
template<typename BasicJsonType>
1174
void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
1175
{
1176
    arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
1177
}
1178
1179
template <typename BasicJsonType, typename T, std::size_t N>
1180
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
1181
                          priority_tag<2> /*unused*/)
1182
-> decltype(j.template get<T>(), void())
1183
{
1184
    for (std::size_t i = 0; i < N; ++i)
1185
    {
1186
        arr[i] = j.at(i).template get<T>();
1187
    }
1188
}
1189
1190
template<typename BasicJsonType, typename CompatibleArrayType>
1191
auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/)
1192
-> decltype(
1193
    arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
1194
    j.template get<typename CompatibleArrayType::value_type>(),
1195
    void())
1196
{
1197
    using std::end;
1198
1199
    arr.reserve(j.size());
1200
    std::transform(j.begin(), j.end(),
1201
                   std::inserter(arr, end(arr)), [](const BasicJsonType & i)
1202
    {
1203
        // get<BasicJsonType>() returns *this, this won't call a from_json
1204
        // method when value_type is BasicJsonType
1205
        return i.template get<typename CompatibleArrayType::value_type>();
1206
    });
1207
}
1208
1209
template <typename BasicJsonType, typename CompatibleArrayType>
1210
void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr,
1211
                          priority_tag<0> /*unused*/)
1212
{
1213
    using std::end;
1214
1215
    std::transform(
1216
        j.begin(), j.end(), std::inserter(arr, end(arr)),
1217
        [](const BasicJsonType & i)
1218
    {
1219
        // get<BasicJsonType>() returns *this, this won't call a from_json
1220
        // method when value_type is BasicJsonType
1221
        return i.template get<typename CompatibleArrayType::value_type>();
1222
    });
1223
}
1224
1225
template <typename BasicJsonType, typename CompatibleArrayType,
1226
          enable_if_t <
1227
              is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
1228
              not is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value and
1229
              not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
1230
              not is_basic_json<CompatibleArrayType>::value,
1231
              int > = 0 >
1232
1233
auto from_json(const BasicJsonType& j, CompatibleArrayType& arr)
1234
-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
1235
j.template get<typename CompatibleArrayType::value_type>(),
1236
void())
1237
{
1238
    if (JSON_UNLIKELY(not j.is_array()))
1239
    {
1240
        JSON_THROW(type_error::create(302, "type must be array, but is " +
1241
                                      std::string(j.type_name())));
1242
    }
1243
1244
    from_json_array_impl(j, arr, priority_tag<3> {});
1245
}
1246
1247
template<typename BasicJsonType, typename CompatibleObjectType,
1248
         enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
1249
void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
1250
{
1251
    if (JSON_UNLIKELY(not j.is_object()))
1252
    {
1253
        JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
1254
    }
1255
1256
    auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
1257
    using value_type = typename CompatibleObjectType::value_type;
1258
    std::transform(
1259
        inner_object->begin(), inner_object->end(),
1260
        std::inserter(obj, obj.begin()),
1261
        [](typename BasicJsonType::object_t::value_type const & p)
1262
    {
1263
        return value_type(p.first, p.second.template get<typename CompatibleObjectType::mapped_type>());
1264
    });
1265
}
1266
1267
// overload for arithmetic types, not chosen for basic_json template arguments
1268
// (BooleanType, etc..); note: Is it really necessary to provide explicit
1269
// overloads for boolean_t etc. in case of a custom BooleanType which is not
1270
// an arithmetic type?
1271
template<typename BasicJsonType, typename ArithmeticType,
1272
         enable_if_t <
1273
             std::is_arithmetic<ArithmeticType>::value and
1274
             not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
1275
             not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
1276
             not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
1277
             not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1278
             int> = 0>
1279
void from_json(const BasicJsonType& j, ArithmeticType& val)
608
1280
{
608
1281
    switch (static_cast<value_t>(j))
608
1282
    {
608
1283
        case value_t::number_unsigned:
608
1284
        {
608
1285
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
608
1286
            break;
608
1287
        }
0
1288
        case value_t::number_integer:
0
1289
        {
0
1290
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
0
1291
            break;
608
1292
        }
0
1293
        case value_t::number_float:
0
1294
        {
0
1295
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
0
1296
            break;
608
1297
        }
0
1298
        case value_t::boolean:
0
1299
        {
0
1300
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
0
1301
            break;
608
1302
        }
608
1303
0
1304
        default:
0
1305
            JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
608
1306
    }
608
1307
}
1308
1309
template<typename BasicJsonType, typename A1, typename A2>
1310
void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
1311
{
1312
    p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
1313
}
1314
1315
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
1316
void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...>)
1317
{
1318
    t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
1319
}
1320
1321
template<typename BasicJsonType, typename... Args>
1322
void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
1323
{
1324
    from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
1325
}
1326
1327
template <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
1328
          typename = enable_if_t<not std::is_constructible<
1329
                                     typename BasicJsonType::string_t, Key>::value>>
1330
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
1331
{
1332
    if (JSON_UNLIKELY(not j.is_array()))
1333
    {
1334
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1335
    }
1336
    for (const auto& p : j)
1337
    {
1338
        if (JSON_UNLIKELY(not p.is_array()))
1339
        {
1340
            JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1341
        }
1342
        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1343
    }
1344
}
1345
1346
template <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
1347
          typename = enable_if_t<not std::is_constructible<
1348
                                     typename BasicJsonType::string_t, Key>::value>>
1349
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
1350
{
1351
    if (JSON_UNLIKELY(not j.is_array()))
1352
    {
1353
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1354
    }
1355
    for (const auto& p : j)
1356
    {
1357
        if (JSON_UNLIKELY(not p.is_array()))
1358
        {
1359
            JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1360
        }
1361
        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1362
    }
1363
}
1364
1365
struct from_json_fn
1366
{
1367
    template<typename BasicJsonType, typename T>
1368
    auto operator()(const BasicJsonType& j, T& val) const
1369
    noexcept(noexcept(from_json(j, val)))
1370
    -> decltype(from_json(j, val), void())
32.4k
1371
    {
32.4k
1372
        return from_json(j, val);
32.4k
1373
    }
_ZNK8nlohmann6detail12from_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEiEEDTcmcl9from_jsonfp_fp0_Ecvv_EERKT_RT0_
608
1371
    {
608
1372
        return from_json(j, val);
608
1373
    }
_ZNK8nlohmann6detail12from_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEESB_EEDTcmcl9from_jsonfp_fp0_Ecvv_EERKT_RT0_
31.2k
1371
    {
31.2k
1372
        return from_json(j, val);
31.2k
1373
    }
_ZNK8nlohmann6detail12from_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEbEEDTcmcl9from_jsonfp_fp0_Ecvv_EERKT_RT0_
8
1371
    {
8
1372
        return from_json(j, val);
8
1373
    }
_ZNK8nlohmann6detail12from_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEdEEDTcmcl9from_jsonfp_fp0_Ecvv_EERKT_RT0_
592
1371
    {
592
1372
        return from_json(j, val);
592
1373
    }
1374
};
1375
}
1376
1377
/// namespace to hold default `from_json` function
1378
/// to see why this is required:
1379
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
1380
namespace
1381
{
1382
constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
1383
}
1384
}
1385
1386
// #include <nlohmann/detail/conversions/to_json.hpp>
1387
1388
1389
#include <ciso646> // or, and, not
1390
#include <iterator> // begin, end
1391
#include <tuple> // tuple, get
1392
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
1393
#include <utility> // move, forward, declval, pair
1394
#include <valarray> // valarray
1395
#include <vector> // vector
1396
1397
// #include <nlohmann/detail/meta/cpp_future.hpp>
1398
1399
// #include <nlohmann/detail/meta/type_traits.hpp>
1400
1401
// #include <nlohmann/detail/value_t.hpp>
1402
1403
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
1404
1405
1406
#include <cstddef> // size_t
1407
#include <string> // string, to_string
1408
#include <iterator> // input_iterator_tag
1409
1410
// #include <nlohmann/detail/value_t.hpp>
1411
1412
1413
namespace nlohmann
1414
{
1415
namespace detail
1416
{
1417
/// proxy class for the items() function
1418
template<typename IteratorType> class iteration_proxy
1419
{
1420
  private:
1421
    /// helper class for iteration
1422
    class iteration_proxy_internal
1423
    {
1424
      public:
1425
        using difference_type = std::ptrdiff_t;
1426
        using value_type = iteration_proxy_internal;
1427
        using pointer = iteration_proxy_internal*;
1428
        using reference = iteration_proxy_internal&;
1429
        using iterator_category = std::input_iterator_tag;
1430
1431
      private:
1432
        /// the iterator
1433
        IteratorType anchor;
1434
        /// an index for arrays (used to create key names)
1435
        std::size_t array_index = 0;
1436
        /// last stringified array index
1437
        mutable std::size_t array_index_last = 0;
1438
        /// a string representation of the array index
1439
        mutable std::string array_index_str = "0";
1440
        /// an empty string (to return a reference for primitive values)
1441
        const std::string empty_str = "";
1442
1443
      public:
0
1444
        explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {}
1445
1446
        iteration_proxy_internal(const iteration_proxy_internal&) = default;
1447
        iteration_proxy_internal& operator=(const iteration_proxy_internal&) = default;
1448
1449
        /// dereference operator (needed for range-based for)
1450
        iteration_proxy_internal& operator*()
0
1451
        {
0
1452
            return *this;
0
1453
        }
1454
1455
        /// increment operator (needed for range-based for)
1456
        iteration_proxy_internal& operator++()
0
1457
        {
0
1458
            ++anchor;
0
1459
            ++array_index;
0
1460
0
1461
            return *this;
0
1462
        }
1463
1464
        /// equality operator (needed for InputIterator)
1465
        bool operator==(const iteration_proxy_internal& o) const noexcept
0
1466
        {
0
1467
            return anchor == o.anchor;
0
1468
        }
1469
1470
        /// inequality operator (needed for range-based for)
1471
        bool operator!=(const iteration_proxy_internal& o) const noexcept
0
1472
        {
0
1473
            return anchor != o.anchor;
0
1474
        }
1475
1476
        /// return key of the iterator
1477
        const std::string& key() const
0
1478
        {
0
1479
            assert(anchor.m_object != nullptr);
0
1480
0
1481
            switch (anchor.m_object->type())
0
1482
            {
0
1483
                // use integer array index as key
0
1484
                case value_t::array:
0
1485
                {
0
1486
                    if (array_index != array_index_last)
0
1487
                    {
0
1488
                        array_index_str = std::to_string(array_index);
0
1489
                        array_index_last = array_index;
0
1490
                    }
0
1491
                    return array_index_str;
0
1492
                }
0
1493
0
1494
                // use key from the object
0
1495
                case value_t::object:
0
1496
                    return anchor.key();
0
1497
0
1498
                // use an empty key for all primitive types
0
1499
                default:
0
1500
                    return empty_str;
0
1501
            }
0
1502
        }
1503
1504
        /// return value of the iterator
1505
        typename IteratorType::reference value() const
0
1506
        {
0
1507
            return anchor.value();
0
1508
        }
1509
    };
1510
1511
    /// the container to iterate
1512
    typename IteratorType::reference container;
1513
1514
  public:
1515
    /// construct iteration proxy from a container
1516
    explicit iteration_proxy(typename IteratorType::reference cont) noexcept
1517
        : container(cont) {}
1518
1519
    /// return iterator begin (needed for range-based for)
1520
    iteration_proxy_internal begin() noexcept
1521
    {
1522
        return iteration_proxy_internal(container.begin());
1523
    }
1524
1525
    /// return iterator end (needed for range-based for)
1526
    iteration_proxy_internal end() noexcept
1527
    {
1528
        return iteration_proxy_internal(container.end());
1529
    }
1530
};
1531
}
1532
}
1533
1534
1535
namespace nlohmann
1536
{
1537
namespace detail
1538
{
1539
//////////////////
1540
// constructors //
1541
//////////////////
1542
1543
template<value_t> struct external_constructor;
1544
1545
template<>
1546
struct external_constructor<value_t::boolean>
1547
{
1548
    template<typename BasicJsonType>
1549
    static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
1.66k
1550
    {
1.66k
1551
        j.m_type = value_t::boolean;
1.66k
1552
        j.m_value = b;
1.66k
1553
        j.assert_invariant();
1.66k
1554
    }
1555
};
1556
1557
template<>
1558
struct external_constructor<value_t::string>
1559
{
1560
    template<typename BasicJsonType>
1561
    static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
172k
1562
    {
172k
1563
        j.m_type = value_t::string;
172k
1564
        j.m_value = s;
172k
1565
        j.assert_invariant();
172k
1566
    }
1567
1568
    template<typename BasicJsonType>
1569
    static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
1.47k
1570
    {
1.47k
1571
        j.m_type = value_t::string;
1.47k
1572
        j.m_value = std::move(s);
1.47k
1573
        j.assert_invariant();
1.47k
1574
    }
1575
1576
    template<typename BasicJsonType, typename CompatibleStringType,
1577
             enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
1578
                         int> = 0>
1579
    static void construct(BasicJsonType& j, const CompatibleStringType& str)
592
1580
    {
592
1581
        j.m_type = value_t::string;
592
1582
        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
592
1583
        j.assert_invariant();
592
1584
    }
_ZN8nlohmann6detail20external_constructorILNS0_7value_tE3EE9constructINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEA6_cLi0EEEvRT_RKT0_
4
1580
    {
4
1581
        j.m_type = value_t::string;
4
1582
        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
4
1583
        j.assert_invariant();
4
1584
    }
_ZN8nlohmann6detail20external_constructorILNS0_7value_tE3EE9constructINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEPKcLi0EEEvRT_RKT0_
40
1580
    {
40
1581
        j.m_type = value_t::string;
40
1582
        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
40
1583
        j.assert_invariant();
40
1584
    }
_ZN8nlohmann6detail20external_constructorILNS0_7value_tE3EE9constructINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEA474_cLi0EEEvRT_RKT0_
548
1580
    {
548
1581
        j.m_type = value_t::string;
548
1582
        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
548
1583
        j.assert_invariant();
548
1584
    }
1585
};
1586
1587
template<>
1588
struct external_constructor<value_t::number_float>
1589
{
1590
    template<typename BasicJsonType>
1591
    static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
158k
1592
    {
158k
1593
        j.m_type = value_t::number_float;
158k
1594
        j.m_value = val;
158k
1595
        j.assert_invariant();
158k
1596
    }
1597
};
1598
1599
template<>
1600
struct external_constructor<value_t::number_unsigned>
1601
{
1602
    template<typename BasicJsonType>
1603
    static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
212k
1604
    {
212k
1605
        j.m_type = value_t::number_unsigned;
212k
1606
        j.m_value = val;
212k
1607
        j.assert_invariant();
212k
1608
    }
1609
};
1610
1611
template<>
1612
struct external_constructor<value_t::number_integer>
1613
{
1614
    template<typename BasicJsonType>
1615
    static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
25.3k
1616
    {
25.3k
1617
        j.m_type = value_t::number_integer;
25.3k
1618
        j.m_value = val;
25.3k
1619
        j.assert_invariant();
25.3k
1620
    }
1621
};
1622
1623
template<>
1624
struct external_constructor<value_t::array>
1625
{
1626
    template<typename BasicJsonType>
1627
    static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
1628
    {
1629
        j.m_type = value_t::array;
1630
        j.m_value = arr;
1631
        j.assert_invariant();
1632
    }
1633
1634
    template<typename BasicJsonType>
1635
    static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1636
    {
1637
        j.m_type = value_t::array;
1638
        j.m_value = std::move(arr);
1639
        j.assert_invariant();
1640
    }
1641
1642
    template<typename BasicJsonType, typename CompatibleArrayType,
1643
             enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
1644
                         int> = 0>
1645
    static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
1646
    {
1647
        using std::begin;
1648
        using std::end;
1649
        j.m_type = value_t::array;
1650
        j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
1651
        j.assert_invariant();
1652
    }
1653
1654
    template<typename BasicJsonType>
1655
    static void construct(BasicJsonType& j, const std::vector<bool>& arr)
1656
    {
1657
        j.m_type = value_t::array;
1658
        j.m_value = value_t::array;
1659
        j.m_value.array->reserve(arr.size());
1660
        for (const bool x : arr)
1661
        {
1662
            j.m_value.array->push_back(x);
1663
        }
1664
        j.assert_invariant();
1665
    }
1666
1667
    template<typename BasicJsonType, typename T,
1668
             enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
1669
    static void construct(BasicJsonType& j, const std::valarray<T>& arr)
1670
    {
1671
        j.m_type = value_t::array;
1672
        j.m_value = value_t::array;
1673
        j.m_value.array->resize(arr.size());
1674
        std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
1675
        j.assert_invariant();
1676
    }
1677
};
1678
1679
template<>
1680
struct external_constructor<value_t::object>
1681
{
1682
    template<typename BasicJsonType>
1683
    static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
1684
    {
1685
        j.m_type = value_t::object;
1686
        j.m_value = obj;
1687
        j.assert_invariant();
1688
    }
1689
1690
    template<typename BasicJsonType>
1691
    static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1692
    {
1693
        j.m_type = value_t::object;
1694
        j.m_value = std::move(obj);
1695
        j.assert_invariant();
1696
    }
1697
1698
    template<typename BasicJsonType, typename CompatibleObjectType,
1699
             enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
1700
    static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
1701
    {
1702
        using std::begin;
1703
        using std::end;
1704
1705
        j.m_type = value_t::object;
1706
        j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
1707
        j.assert_invariant();
1708
    }
1709
};
1710
1711
/////////////
1712
// to_json //
1713
/////////////
1714
1715
template<typename BasicJsonType, typename T,
1716
         enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
1717
void to_json(BasicJsonType& j, T b) noexcept
1.66k
1718
{
1.66k
1719
    external_constructor<value_t::boolean>::construct(j, b);
1.66k
1720
}
1721
1722
template<typename BasicJsonType, typename CompatibleString,
1723
         enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
1724
void to_json(BasicJsonType& j, const CompatibleString& s)
173k
1725
{
173k
1726
    external_constructor<value_t::string>::construct(j, s);
173k
1727
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEESA_Li0EEEvRT_RKT0_
172k
1725
{
172k
1726
    external_constructor<value_t::string>::construct(j, s);
172k
1727
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEA6_cLi0EEEvRT_RKT0_
4
1725
{
4
1726
    external_constructor<value_t::string>::construct(j, s);
4
1727
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEPKcLi0EEEvRT_RKT0_
40
1725
{
40
1726
    external_constructor<value_t::string>::construct(j, s);
40
1727
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEA474_cLi0EEEvRT_RKT0_
548
1725
{
548
1726
    external_constructor<value_t::string>::construct(j, s);
548
1727
}
1728
1729
template<typename BasicJsonType>
1730
void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
1.47k
1731
{
1.47k
1732
    external_constructor<value_t::string>::construct(j, std::move(s));
1.47k
1733
}
1734
1735
template<typename BasicJsonType, typename FloatType,
1736
         enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
1737
void to_json(BasicJsonType& j, FloatType val) noexcept
158k
1738
{
158k
1739
    external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
158k
1740
}
1741
1742
template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
1743
         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
1744
void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
212k
1745
{
212k
1746
    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
212k
1747
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEyLi0EEEvRT_T0_
212k
1745
{
212k
1746
    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
212k
1747
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEjLi0EEEvRT_T0_
492
1745
{
492
1746
    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
492
1747
}
1748
1749
template<typename BasicJsonType, typename CompatibleNumberIntegerType,
1750
         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
1751
void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
25.3k
1752
{
25.3k
1753
    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
25.3k
1754
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEiLi0EEEvRT_T0_
4
1752
{
4
1753
    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
4
1754
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEExLi0EEEvRT_T0_
25.3k
1752
{
25.3k
1753
    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
25.3k
1754
}
1755
1756
template<typename BasicJsonType, typename EnumType,
1757
         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
1758
void to_json(BasicJsonType& j, EnumType e) noexcept
1759
{
1760
    using underlying_type = typename std::underlying_type<EnumType>::type;
1761
    external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
1762
}
1763
1764
template<typename BasicJsonType>
1765
void to_json(BasicJsonType& j, const std::vector<bool>& e)
1766
{
1767
    external_constructor<value_t::array>::construct(j, e);
1768
}
1769
1770
template <typename BasicJsonType, typename CompatibleArrayType,
1771
          enable_if_t<is_compatible_array_type<BasicJsonType,
1772
                      CompatibleArrayType>::value and
1773
                      not is_compatible_object_type<
1774
                          BasicJsonType, CompatibleArrayType>::value and
1775
                      not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
1776
                      not is_basic_json<CompatibleArrayType>::value,
1777
                      int> = 0>
1778
void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
1779
{
1780
    external_constructor<value_t::array>::construct(j, arr);
1781
}
1782
1783
template<typename BasicJsonType, typename T,
1784
         enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
1785
void to_json(BasicJsonType& j, const std::valarray<T>& arr)
1786
{
1787
    external_constructor<value_t::array>::construct(j, std::move(arr));
1788
}
1789
1790
template<typename BasicJsonType>
1791
void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1792
{
1793
    external_constructor<value_t::array>::construct(j, std::move(arr));
1794
}
1795
1796
template<typename BasicJsonType, typename CompatibleObjectType,
1797
         enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>
1798
void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
1799
{
1800
    external_constructor<value_t::object>::construct(j, obj);
1801
}
1802
1803
template<typename BasicJsonType>
1804
void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1805
{
1806
    external_constructor<value_t::object>::construct(j, std::move(obj));
1807
}
1808
1809
template <
1810
    typename BasicJsonType, typename T, std::size_t N,
1811
    enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,
1812
                const T (&)[N]>::value,
1813
                int> = 0 >
1814
void to_json(BasicJsonType& j, const T (&arr)[N])
1815
{
1816
    external_constructor<value_t::array>::construct(j, arr);
1817
}
1818
1819
template<typename BasicJsonType, typename... Args>
1820
void to_json(BasicJsonType& j, const std::pair<Args...>& p)
1821
{
1822
    j = {p.first, p.second};
1823
}
1824
1825
// for https://github.com/nlohmann/json/pull/1134
1826
template<typename BasicJsonType, typename T,
1827
         enable_if_t<std::is_same<T, typename iteration_proxy<typename BasicJsonType::iterator>::iteration_proxy_internal>::value, int> = 0>
1828
void to_json(BasicJsonType& j, T b) noexcept
1829
{
1830
    j = {{b.key(), b.value()}};
1831
}
1832
1833
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
1834
void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)
1835
{
1836
    j = {std::get<Idx>(t)...};
1837
}
1838
1839
template<typename BasicJsonType, typename... Args>
1840
void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
1841
{
1842
    to_json_tuple_impl(j, t, index_sequence_for<Args...> {});
1843
}
1844
1845
struct to_json_fn
1846
{
1847
    template<typename BasicJsonType, typename T>
1848
    auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
1849
    -> decltype(to_json(j, std::forward<T>(val)), void())
573k
1850
    {
573k
1851
        return to_json(j, std::forward<T>(val));
573k
1852
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEKSB_EEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
164
1850
    {
164
1851
        return to_json(j, std::forward<T>(val));
164
1852
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEERA474_KcEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSH_
548
1850
    {
548
1851
        return to_json(j, std::forward<T>(val));
548
1852
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEESB_EEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
1.47k
1850
    {
1.47k
1851
        return to_json(j, std::forward<T>(val));
1.47k
1852
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEERjEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
492
1850
    {
492
1851
        return to_json(j, std::forward<T>(val));
492
1852
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEERKPKcEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSI_
40
1850
    {
40
1851
        return to_json(j, std::forward<T>(val));
40
1852
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEbEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
4
1850
    {
4
1851
        return to_json(j, std::forward<T>(val));
4
1852
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEdEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
4
1850
    {
4
1851
        return to_json(j, std::forward<T>(val));
4
1852
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEERA6_KcEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSH_
4
1850
    {
4
1851
        return to_json(j, std::forward<T>(val));
4
1852
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEiEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
4
1850
    {
4
1851
        return to_json(j, std::forward<T>(val));
4
1852
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEERxEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
25.3k
1850
    {
25.3k
1851
        return to_json(j, std::forward<T>(val));
25.3k
1852
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEERdEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
158k
1850
    {
158k
1851
        return to_json(j, std::forward<T>(val));
158k
1852
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEERyEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
212k
1850
    {
212k
1851
        return to_json(j, std::forward<T>(val));
212k
1852
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEERSB_EEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
172k
1850
    {
172k
1851
        return to_json(j, std::forward<T>(val));
172k
1852
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEERbEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
1.66k
1850
    {
1.66k
1851
        return to_json(j, std::forward<T>(val));
1.66k
1852
    }
1853
};
1854
}
1855
1856
/// namespace to hold default `to_json` function
1857
namespace
1858
{
1859
constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
1860
}
1861
}
1862
1863
// #include <nlohmann/detail/input/input_adapters.hpp>
1864
1865
1866
#include <cassert> // assert
1867
#include <cstddef> // size_t
1868
#include <cstring> // strlen
1869
#include <istream> // istream
1870
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
1871
#include <memory> // shared_ptr, make_shared, addressof
1872
#include <numeric> // accumulate
1873
#include <string> // string, char_traits
1874
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
1875
#include <utility> // pair, declval
1876
1877
// #include <nlohmann/detail/macro_scope.hpp>
1878
1879
1880
namespace nlohmann
1881
{
1882
namespace detail
1883
{
1884
/// the supported input formats
1885
enum class input_format_t { json, cbor, msgpack, ubjson };
1886
1887
////////////////////
1888
// input adapters //
1889
////////////////////
1890
1891
/*!
1892
@brief abstract input adapter interface
1893
1894
Produces a stream of std::char_traits<char>::int_type characters from a
1895
std::istream, a buffer, or some other input type. Accepts the return of
1896
exactly one non-EOF character for future input. The int_type characters
1897
returned consist of all valid char values as positive values (typically
1898
unsigned char), plus an EOF value outside that range, specified by the value
1899
of the function std::char_traits<char>::eof(). This value is typically -1, but
1900
could be any arbitrary value which is not a valid char value.
1901
*/
1902
struct input_adapter_protocol
1903
{
1904
    /// get a character [0,255] or std::char_traits<char>::eof().
1905
    virtual std::char_traits<char>::int_type get_character() = 0;
2.34k
1906
    virtual ~input_adapter_protocol() = default;
1907
};
1908
1909
/// a type to simplify interfaces
1910
using input_adapter_t = std::shared_ptr<input_adapter_protocol>;
1911
1912
/*!
1913
Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
1914
beginning of input. Does not support changing the underlying std::streambuf
1915
in mid-input. Maintains underlying std::istream and std::streambuf to support
1916
subsequent use of standard std::istream operations to process any input
1917
characters following those used in parsing the JSON input.  Clears the
1918
std::istream flags; any input errors (e.g., EOF) will be detected by the first
1919
subsequent call for input from the std::istream.
1920
*/
1921
class input_stream_adapter : public input_adapter_protocol
1922
{
1923
  public:
1924
    ~input_stream_adapter() override
540
1925
    {
540
1926
        // clear stream flags; we use underlying streambuf I/O, do not
540
1927
        // maintain ifstream flags
540
1928
        is.clear();
540
1929
    }
1930
1931
    explicit input_stream_adapter(std::istream& i)
1932
        : is(i), sb(*i.rdbuf())
540
1933
    {}
1934
1935
    // delete because of pointer members
1936
    input_stream_adapter(const input_stream_adapter&) = delete;
1937
    input_stream_adapter& operator=(input_stream_adapter&) = delete;
1938
1939
    // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
1940
    // ensure that std::char_traits<char>::eof() and the character 0xFF do not
1941
    // end up as the same value, eg. 0xFFFFFFFF.
1942
    std::char_traits<char>::int_type get_character() override
1.17M
1943
    {
1.17M
1944
        return sb.sbumpc();
1.17M
1945
    }
1946
1947
  private:
1948
    /// the associated input stream
1949
    std::istream& is;
1950
    std::streambuf& sb;
1951
};
1952
1953
/// input adapter for buffer input
1954
class input_buffer_adapter : public input_adapter_protocol
1955
{
1956
  public:
1957
    input_buffer_adapter(const char* b, const std::size_t l)
1958
        : cursor(b), limit(b + l)
1.80k
1959
    {}
1960
1961
    // delete because of pointer members
1962
    input_buffer_adapter(const input_buffer_adapter&) = delete;
1963
    input_buffer_adapter& operator=(input_buffer_adapter&) = delete;
1964
1965
    std::char_traits<char>::int_type get_character() noexcept override
11.3M
1966
    {
11.3M
1967
        if (JSON_LIKELY(cursor < limit))
11.3M
1968
        {
11.3M
1969
            return std::char_traits<char>::to_int_type(*(cursor++));
11.3M
1970
        }
11.3M
1971
160
1972
        return std::char_traits<char>::eof();
11.3M
1973
    }
1974
1975
  private:
1976
    /// pointer to the current character
1977
    const char* cursor;
1978
    /// pointer past the last character
1979
    const char* const limit;
1980
};
1981
1982
template<typename WideStringType>
1983
class wide_string_input_adapter : public input_adapter_protocol
1984
{
1985
  public:
1986
    explicit wide_string_input_adapter(const WideStringType& w) : str(w) {}
1987
1988
    std::char_traits<char>::int_type get_character() noexcept override
0
1989
    {
0
1990
        // check if buffer needs to be filled
0
1991
        if (utf8_bytes_index == utf8_bytes_filled)
0
1992
        {
0
1993
            if (sizeof(typename WideStringType::value_type) == 2)
0
1994
            {
0
1995
                fill_buffer_utf16();
0
1996
            }
0
1997
            else
0
1998
            {
0
1999
                fill_buffer_utf32();
0
2000
            }
0
2001
0
2002
            assert(utf8_bytes_filled > 0);
0
2003
            assert(utf8_bytes_index == 0);
0
2004
        }
0
2005
0
2006
        // use buffer
0
2007
        assert(utf8_bytes_filled > 0);
0
2008
        assert(utf8_bytes_index < utf8_bytes_filled);
0
2009
        return utf8_bytes[utf8_bytes_index++];
0
2010
    }
_ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEEEE13get_characterEv
0
1989
    {
0
1990
        // check if buffer needs to be filled
0
1991
        if (utf8_bytes_index == utf8_bytes_filled)
0
1992
        {
0
1993
            if (sizeof(typename WideStringType::value_type) == 2)
0
1994
            {
0
1995
                fill_buffer_utf16();
0
1996
            }
0
1997
            else
0
1998
            {
0
1999
                fill_buffer_utf32();
0
2000
            }
0
2001
0
2002
            assert(utf8_bytes_filled > 0);
0
2003
            assert(utf8_bytes_index == 0);
0
2004
        }
0
2005
0
2006
        // use buffer
0
2007
        assert(utf8_bytes_filled > 0);
0
2008
        assert(utf8_bytes_index < utf8_bytes_filled);
0
2009
        return utf8_bytes[utf8_bytes_index++];
0
2010
    }
_ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDiSt11char_traitsIDiESaIDiEEEE13get_characterEv
0
1989
    {
0
1990
        // check if buffer needs to be filled
0
1991
        if (utf8_bytes_index == utf8_bytes_filled)
0
1992
        {
0
1993
            if (sizeof(typename WideStringType::value_type) == 2)
0
1994
            {
0
1995
                fill_buffer_utf16();
0
1996
            }
0
1997
            else
0
1998
            {
0
1999
                fill_buffer_utf32();
0
2000
            }
0
2001
0
2002
            assert(utf8_bytes_filled > 0);
0
2003
            assert(utf8_bytes_index == 0);
0
2004
        }
0
2005
0
2006
        // use buffer
0
2007
        assert(utf8_bytes_filled > 0);
0
2008
        assert(utf8_bytes_index < utf8_bytes_filled);
0
2009
        return utf8_bytes[utf8_bytes_index++];
0
2010
    }
_ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEEEE13get_characterEv
0
1989
    {
0
1990
        // check if buffer needs to be filled
0
1991
        if (utf8_bytes_index == utf8_bytes_filled)
0
1992
        {
0
1993
            if (sizeof(typename WideStringType::value_type) == 2)
0
1994
            {
0
1995
                fill_buffer_utf16();
0
1996
            }
0
1997
            else
0
1998
            {
0
1999
                fill_buffer_utf32();
0
2000
            }
0
2001
0
2002
            assert(utf8_bytes_filled > 0);
0
2003
            assert(utf8_bytes_index == 0);
0
2004
        }
0
2005
0
2006
        // use buffer
0
2007
        assert(utf8_bytes_filled > 0);
0
2008
        assert(utf8_bytes_index < utf8_bytes_filled);
0
2009
        return utf8_bytes[utf8_bytes_index++];
0
2010
    }
2011
2012
  private:
2013
    void fill_buffer_utf16()
0
2014
    {
0
2015
        utf8_bytes_index = 0;
0
2016
0
2017
        if (current_wchar == str.size())
0
2018
        {
0
2019
            utf8_bytes[0] = std::char_traits<char>::eof();
0
2020
            utf8_bytes_filled = 1;
0
2021
        }
0
2022
        else
0
2023
        {
0
2024
            // get the current character
0
2025
            const int wc = static_cast<int>(str[current_wchar++]);
0
2026
0
2027
            // UTF-16 to UTF-8 encoding
0
2028
            if (wc < 0x80)
0
2029
            {
0
2030
                utf8_bytes[0] = wc;
0
2031
                utf8_bytes_filled = 1;
0
2032
            }
0
2033
            else if (wc <= 0x7FF)
0
2034
            {
0
2035
                utf8_bytes[0] = 0xC0 | ((wc >> 6));
0
2036
                utf8_bytes[1] = 0x80 | (wc & 0x3F);
0
2037
                utf8_bytes_filled = 2;
0
2038
            }
0
2039
            else if (0xD800 > wc or wc >= 0xE000)
0
2040
            {
0
2041
                utf8_bytes[0] = 0xE0 | ((wc >> 12));
0
2042
                utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
0
2043
                utf8_bytes[2] = 0x80 | (wc & 0x3F);
0
2044
                utf8_bytes_filled = 3;
0
2045
            }
0
2046
            else
0
2047
            {
0
2048
                if (current_wchar < str.size())
0
2049
                {
0
2050
                    const int wc2 = static_cast<int>(str[current_wchar++]);
0
2051
                    const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
0
2052
                    utf8_bytes[0] = 0xf0 | (charcode >> 18);
0
2053
                    utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
0
2054
                    utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
0
2055
                    utf8_bytes[3] = 0x80 | (charcode & 0x3F);
0
2056
                    utf8_bytes_filled = 4;
0
2057
                }
0
2058
                else
0
2059
                {
0
2060
                    // unknown character
0
2061
                    ++current_wchar;
0
2062
                    utf8_bytes[0] = wc;
0
2063
                    utf8_bytes_filled = 1;
0
2064
                }
0
2065
            }
0
2066
        }
0
2067
    }
_ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEEEE17fill_buffer_utf16Ev
0
2014
    {
0
2015
        utf8_bytes_index = 0;
0
2016
0
2017
        if (current_wchar == str.size())
0
2018
        {
0
2019
            utf8_bytes[0] = std::char_traits<char>::eof();
0
2020
            utf8_bytes_filled = 1;
0
2021
        }
0
2022
        else
0
2023
        {
0
2024
            // get the current character
0
2025
            const int wc = static_cast<int>(str[current_wchar++]);
0
2026
0
2027
            // UTF-16 to UTF-8 encoding
0
2028
            if (wc < 0x80)
0
2029
            {
0
2030
                utf8_bytes[0] = wc;
0
2031
                utf8_bytes_filled = 1;
0
2032
            }
0
2033
            else if (wc <= 0x7FF)
0
2034
            {
0
2035
                utf8_bytes[0] = 0xC0 | ((wc >> 6));
0
2036
                utf8_bytes[1] = 0x80 | (wc & 0x3F);
0
2037
                utf8_bytes_filled = 2;
0
2038
            }
0
2039
            else if (0xD800 > wc or wc >= 0xE000)
0
2040
            {
0
2041
                utf8_bytes[0] = 0xE0 | ((wc >> 12));
0
2042
                utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
0
2043
                utf8_bytes[2] = 0x80 | (wc & 0x3F);
0
2044
                utf8_bytes_filled = 3;
0
2045
            }
0
2046
            else
0
2047
            {
0
2048
                if (current_wchar < str.size())
0
2049
                {
0
2050
                    const int wc2 = static_cast<int>(str[current_wchar++]);
0
2051
                    const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
0
2052
                    utf8_bytes[0] = 0xf0 | (charcode >> 18);
0
2053
                    utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
0
2054
                    utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
0
2055
                    utf8_bytes[3] = 0x80 | (charcode & 0x3F);
0
2056
                    utf8_bytes_filled = 4;
0
2057
                }
0
2058
                else
0
2059
                {
0
2060
                    // unknown character
0
2061
                    ++current_wchar;
0
2062
                    utf8_bytes[0] = wc;
0
2063
                    utf8_bytes_filled = 1;
0
2064
                }
0
2065
            }
0
2066
        }
0
2067
    }
_ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDiSt11char_traitsIDiESaIDiEEEE17fill_buffer_utf16Ev
0
2014
    {
0
2015
        utf8_bytes_index = 0;
0
2016
0
2017
        if (current_wchar == str.size())
0
2018
        {
0
2019
            utf8_bytes[0] = std::char_traits<char>::eof();
0
2020
            utf8_bytes_filled = 1;
0
2021
        }
0
2022
        else
0
2023
        {
0
2024
            // get the current character
0
2025
            const int wc = static_cast<int>(str[current_wchar++]);
0
2026
0
2027
            // UTF-16 to UTF-8 encoding
0
2028
            if (wc < 0x80)
0
2029
            {
0
2030
                utf8_bytes[0] = wc;
0
2031
                utf8_bytes_filled = 1;
0
2032
            }
0
2033
            else if (wc <= 0x7FF)
0
2034
            {
0
2035
                utf8_bytes[0] = 0xC0 | ((wc >> 6));
0
2036
                utf8_bytes[1] = 0x80 | (wc & 0x3F);
0
2037
                utf8_bytes_filled = 2;
0
2038
            }
0
2039
            else if (0xD800 > wc or wc >= 0xE000)
0
2040
            {
0
2041
                utf8_bytes[0] = 0xE0 | ((wc >> 12));
0
2042
                utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
0
2043
                utf8_bytes[2] = 0x80 | (wc & 0x3F);
0
2044
                utf8_bytes_filled = 3;
0
2045
            }
0
2046
            else
0
2047
            {
0
2048
                if (current_wchar < str.size())
0
2049
                {
0
2050
                    const int wc2 = static_cast<int>(str[current_wchar++]);
0
2051
                    const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
0
2052
                    utf8_bytes[0] = 0xf0 | (charcode >> 18);
0
2053
                    utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
0
2054
                    utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
0
2055
                    utf8_bytes[3] = 0x80 | (charcode & 0x3F);
0
2056
                    utf8_bytes_filled = 4;
0
2057
                }
0
2058
                else
0
2059
                {
0
2060
                    // unknown character
0
2061
                    ++current_wchar;
0
2062
                    utf8_bytes[0] = wc;
0
2063
                    utf8_bytes_filled = 1;
0
2064
                }
0
2065
            }
0
2066
        }
0
2067
    }
_ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEEEE17fill_buffer_utf16Ev
0
2014
    {
0
2015
        utf8_bytes_index = 0;
0
2016
0
2017
        if (current_wchar == str.size())
0
2018
        {
0
2019
            utf8_bytes[0] = std::char_traits<char>::eof();
0
2020
            utf8_bytes_filled = 1;
0
2021
        }
0
2022
        else
0
2023
        {
0
2024
            // get the current character
0
2025
            const int wc = static_cast<int>(str[current_wchar++]);
0
2026
0
2027
            // UTF-16 to UTF-8 encoding
0
2028
            if (wc < 0x80)
0
2029
            {
0
2030
                utf8_bytes[0] = wc;
0
2031
                utf8_bytes_filled = 1;
0
2032
            }
0
2033
            else if (wc <= 0x7FF)
0
2034
            {
0
2035
                utf8_bytes[0] = 0xC0 | ((wc >> 6));
0
2036
                utf8_bytes[1] = 0x80 | (wc & 0x3F);
0
2037
                utf8_bytes_filled = 2;
0
2038
            }
0
2039
            else if (0xD800 > wc or wc >= 0xE000)
0
2040
            {
0
2041
                utf8_bytes[0] = 0xE0 | ((wc >> 12));
0
2042
                utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
0
2043
                utf8_bytes[2] = 0x80 | (wc & 0x3F);
0
2044
                utf8_bytes_filled = 3;
0
2045
            }
0
2046
            else
0
2047
            {
0
2048
                if (current_wchar < str.size())
0
2049
                {
0
2050
                    const int wc2 = static_cast<int>(str[current_wchar++]);
0
2051
                    const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
0
2052
                    utf8_bytes[0] = 0xf0 | (charcode >> 18);
0
2053
                    utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
0
2054
                    utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
0
2055
                    utf8_bytes[3] = 0x80 | (charcode & 0x3F);
0
2056
                    utf8_bytes_filled = 4;
0
2057
                }
0
2058
                else
0
2059
                {
0
2060
                    // unknown character
0
2061
                    ++current_wchar;
0
2062
                    utf8_bytes[0] = wc;
0
2063
                    utf8_bytes_filled = 1;
0
2064
                }
0
2065
            }
0
2066
        }
0
2067
    }
2068
2069
    void fill_buffer_utf32()
0
2070
    {
0
2071
        utf8_bytes_index = 0;
0
2072
0
2073
        if (current_wchar == str.size())
0
2074
        {
0
2075
            utf8_bytes[0] = std::char_traits<char>::eof();
0
2076
            utf8_bytes_filled = 1;
0
2077
        }
0
2078
        else
0
2079
        {
0
2080
            // get the current character
0
2081
            const int wc = static_cast<int>(str[current_wchar++]);
0
2082
0
2083
            // UTF-32 to UTF-8 encoding
0
2084
            if (wc < 0x80)
0
2085
            {
0
2086
                utf8_bytes[0] = wc;
0
2087
                utf8_bytes_filled = 1;
0
2088
            }
0
2089
            else if (wc <= 0x7FF)
0
2090
            {
0
2091
                utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
0
2092
                utf8_bytes[1] = 0x80 | (wc & 0x3F);
0
2093
                utf8_bytes_filled = 2;
0
2094
            }
0
2095
            else if (wc <= 0xFFFF)
0
2096
            {
0
2097
                utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
0
2098
                utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
0
2099
                utf8_bytes[2] = 0x80 | (wc & 0x3F);
0
2100
                utf8_bytes_filled = 3;
0
2101
            }
0
2102
            else if (wc <= 0x10FFFF)
0
2103
            {
0
2104
                utf8_bytes[0] = 0xF0 | ((wc >> 18 ) & 0x07);
0
2105
                utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
0
2106
                utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
0
2107
                utf8_bytes[3] = 0x80 | (wc & 0x3F);
0
2108
                utf8_bytes_filled = 4;
0
2109
            }
0
2110
            else
0
2111
            {
0
2112
                // unknown character
0
2113
                utf8_bytes[0] = wc;
0
2114
                utf8_bytes_filled = 1;
0
2115
            }
0
2116
        }
0
2117
    }
_ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEEEE17fill_buffer_utf32Ev
0
2070
    {
0
2071
        utf8_bytes_index = 0;
0
2072
0
2073
        if (current_wchar == str.size())
0
2074
        {
0
2075
            utf8_bytes[0] = std::char_traits<char>::eof();
0
2076
            utf8_bytes_filled = 1;
0
2077
        }
0
2078
        else
0
2079
        {
0
2080
            // get the current character
0
2081
            const int wc = static_cast<int>(str[current_wchar++]);
0
2082
0
2083
            // UTF-32 to UTF-8 encoding
0
2084
            if (wc < 0x80)
0
2085
            {
0
2086
                utf8_bytes[0] = wc;
0
2087
                utf8_bytes_filled = 1;
0
2088
            }
0
2089
            else if (wc <= 0x7FF)
0
2090
            {
0
2091
                utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
0
2092
                utf8_bytes[1] = 0x80 | (wc & 0x3F);
0
2093
                utf8_bytes_filled = 2;
0
2094
            }
0
2095
            else if (wc <= 0xFFFF)
0
2096
            {
0
2097
                utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
0
2098
                utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
0
2099
                utf8_bytes[2] = 0x80 | (wc & 0x3F);
0
2100
                utf8_bytes_filled = 3;
0
2101
            }
0
2102
            else if (wc <= 0x10FFFF)
0
2103
            {
0
2104
                utf8_bytes[0] = 0xF0 | ((wc >> 18 ) & 0x07);
0
2105
                utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
0
2106
                utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
0
2107
                utf8_bytes[3] = 0x80 | (wc & 0x3F);
0
2108
                utf8_bytes_filled = 4;
0
2109
            }
0
2110
            else
0
2111
            {
0
2112
                // unknown character
0
2113
                utf8_bytes[0] = wc;
0
2114
                utf8_bytes_filled = 1;
0
2115
            }
0
2116
        }
0
2117
    }
_ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEEEE17fill_buffer_utf32Ev
0
2070
    {
0
2071
        utf8_bytes_index = 0;
0
2072
0
2073
        if (current_wchar == str.size())
0
2074
        {
0
2075
            utf8_bytes[0] = std::char_traits<char>::eof();
0
2076
            utf8_bytes_filled = 1;
0
2077
        }
0
2078
        else
0
2079
        {
0
2080
            // get the current character
0
2081
            const int wc = static_cast<int>(str[current_wchar++]);
0
2082
0
2083
            // UTF-32 to UTF-8 encoding
0
2084
            if (wc < 0x80)
0
2085
            {
0
2086
                utf8_bytes[0] = wc;
0
2087
                utf8_bytes_filled = 1;
0
2088
            }
0
2089
            else if (wc <= 0x7FF)
0
2090
            {
0
2091
                utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
0
2092
                utf8_bytes[1] = 0x80 | (wc & 0x3F);
0
2093
                utf8_bytes_filled = 2;
0
2094
            }
0
2095
            else if (wc <= 0xFFFF)
0
2096
            {
0
2097
                utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
0
2098
                utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
0
2099
                utf8_bytes[2] = 0x80 | (wc & 0x3F);
0
2100
                utf8_bytes_filled = 3;
0
2101
            }
0
2102
            else if (wc <= 0x10FFFF)
0
2103
            {
0
2104
                utf8_bytes[0] = 0xF0 | ((wc >> 18 ) & 0x07);
0
2105
                utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
0
2106
                utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
0
2107
                utf8_bytes[3] = 0x80 | (wc & 0x3F);
0
2108
                utf8_bytes_filled = 4;
0
2109
            }
0
2110
            else
0
2111
            {
0
2112
                // unknown character
0
2113
                utf8_bytes[0] = wc;
0
2114
                utf8_bytes_filled = 1;
0
2115
            }
0
2116
        }
0
2117
    }
_ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDiSt11char_traitsIDiESaIDiEEEE17fill_buffer_utf32Ev
0
2070
    {
0
2071
        utf8_bytes_index = 0;
0
2072
0
2073
        if (current_wchar == str.size())
0
2074
        {
0
2075
            utf8_bytes[0] = std::char_traits<char>::eof();
0
2076
            utf8_bytes_filled = 1;
0
2077
        }
0
2078
        else
0
2079
        {
0
2080
            // get the current character
0
2081
            const int wc = static_cast<int>(str[current_wchar++]);
0
2082
0
2083
            // UTF-32 to UTF-8 encoding
0
2084
            if (wc < 0x80)
0
2085
            {
0
2086
                utf8_bytes[0] = wc;
0
2087
                utf8_bytes_filled = 1;
0
2088
            }
0
2089
            else if (wc <= 0x7FF)
0
2090
            {
0
2091
                utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
0
2092
                utf8_bytes[1] = 0x80 | (wc & 0x3F);
0
2093
                utf8_bytes_filled = 2;
0
2094
            }
0
2095
            else if (wc <= 0xFFFF)
0
2096
            {
0
2097
                utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
0
2098
                utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
0
2099
                utf8_bytes[2] = 0x80 | (wc & 0x3F);
0
2100
                utf8_bytes_filled = 3;
0
2101
            }
0
2102
            else if (wc <= 0x10FFFF)
0
2103
            {
0
2104
                utf8_bytes[0] = 0xF0 | ((wc >> 18 ) & 0x07);
0
2105
                utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
0
2106
                utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
0
2107
                utf8_bytes[3] = 0x80 | (wc & 0x3F);
0
2108
                utf8_bytes_filled = 4;
0
2109
            }
0
2110
            else
0
2111
            {
0
2112
                // unknown character
0
2113
                utf8_bytes[0] = wc;
0
2114
                utf8_bytes_filled = 1;
0
2115
            }
0
2116
        }
0
2117
    }
2118
2119
  private:
2120
    /// the wstring to process
2121
    const WideStringType& str;
2122
2123
    /// index of the current wchar in str
2124
    std::size_t current_wchar = 0;
2125
2126
    /// a buffer for UTF-8 bytes
2127
    std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
2128
2129
    /// index to the utf8_codes array for the next valid byte
2130
    std::size_t utf8_bytes_index = 0;
2131
    /// number of valid bytes in the utf8_codes array
2132
    std::size_t utf8_bytes_filled = 0;
2133
};
2134
2135
class input_adapter
2136
{
2137
  public:
2138
    // native support
2139
2140
    /// input adapter for input stream
2141
    input_adapter(std::istream& i)
540
2142
        : ia(std::make_shared<input_stream_adapter>(i)) {}
2143
2144
    /// input adapter for input stream
2145
    input_adapter(std::istream&& i)
0
2146
        : ia(std::make_shared<input_stream_adapter>(i)) {}
2147
2148
    input_adapter(const std::wstring& ws)
0
2149
        : ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}
2150
2151
    input_adapter(const std::u16string& ws)
0
2152
        : ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}
2153
2154
    input_adapter(const std::u32string& ws)
0
2155
        : ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}
2156
2157
    /// input adapter for buffer
2158
    template<typename CharT,
2159
             typename std::enable_if<
2160
                 std::is_pointer<CharT>::value and
2161
                 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2162
                 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2163
                 int>::type = 0>
2164
    input_adapter(CharT b, std::size_t l)
2165
        : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {}
2166
2167
    // derived support
2168
2169
    /// input adapter for string literal
2170
    template<typename CharT,
2171
             typename std::enable_if<
2172
                 std::is_pointer<CharT>::value and
2173
                 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2174
                 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2175
                 int>::type = 0>
2176
    input_adapter(CharT b)
2177
        : input_adapter(reinterpret_cast<const char*>(b),
2178
                        std::strlen(reinterpret_cast<const char*>(b))) {}
2179
2180
    /// input adapter for iterator range with contiguous storage
2181
    template<class IteratorType,
2182
             typename std::enable_if<
2183
                 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
2184
                 int>::type = 0>
2185
    input_adapter(IteratorType first, IteratorType last)
1.80k
2186
    {
1.80k
2187
#ifndef NDEBUG
1.80k
2188
        // assertion to check that the iterator range is indeed contiguous,
1.80k
2189
        // see http://stackoverflow.com/a/35008842/266378 for more discussion
1.80k
2190
        const auto is_contiguous = std::accumulate(
1.80k
2191
                                       first, last, std::pair<bool, int>(true, 0),
1.80k
2192
                                       [&first](std::pair<bool, int> res, decltype(*first) val)
11.3M
2193
        {
11.3M
2194
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
11.3M
2195
            return res;
11.3M
2196
        }).first;
_ZZN8nlohmann6detail13input_adapterC1IN9__gnu_cxx17__normal_iteratorIPKcNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEELi0EEET_SE_ENKUlSt4pairIbiERS5_E_clESG_SH_
50.1k
2193
        {
50.1k
2194
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
50.1k
2195
            return res;
50.1k
2196
        }).first;
_ZZN8nlohmann6detail13input_adapterC1IPKcLi0EEET_S5_ENKUlSt4pairIbiERS3_E_clES7_S8_
11.3M
2193
        {
11.3M
2194
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
11.3M
2195
            return res;
11.3M
2196
        }).first;
1.80k
2197
        assert(is_contiguous);
1.80k
2198
#endif
1.80k
2199
1.80k
2200
        // assertion to check that each element is 1 byte long
1.80k
2201
        static_assert(
1.80k
2202
            sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
1.80k
2203
            "each element in the iterator range must have the size of 1 byte");
1.80k
2204
1.80k
2205
        const auto len = static_cast<size_t>(std::distance(first, last));
1.80k
2206
        if (JSON_LIKELY(len > 0))
1.80k
2207
        {
1.80k
2208
            // there is at least one element: use the address of first
1.80k
2209
            ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
1.80k
2210
        }
1.80k
2211
        else
0
2212
        {
0
2213
            // the address of first cannot be used: use nullptr
0
2214
            ia = std::make_shared<input_buffer_adapter>(nullptr, len);
0
2215
        }
1.80k
2216
    }
_ZN8nlohmann6detail13input_adapterC2IN9__gnu_cxx17__normal_iteratorIPKcNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEELi0EEET_SE_
160
2186
    {
160
2187
#ifndef NDEBUG
160
2188
        // assertion to check that the iterator range is indeed contiguous,
160
2189
        // see http://stackoverflow.com/a/35008842/266378 for more discussion
160
2190
        const auto is_contiguous = std::accumulate(
160
2191
                                       first, last, std::pair<bool, int>(true, 0),
160
2192
                                       [&first](std::pair<bool, int> res, decltype(*first) val)
160
2193
        {
160
2194
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
160
2195
            return res;
160
2196
        }).first;
160
2197
        assert(is_contiguous);
160
2198
#endif
160
2199
160
2200
        // assertion to check that each element is 1 byte long
160
2201
        static_assert(
160
2202
            sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
160
2203
            "each element in the iterator range must have the size of 1 byte");
160
2204
160
2205
        const auto len = static_cast<size_t>(std::distance(first, last));
160
2206
        if (JSON_LIKELY(len > 0))
160
2207
        {
160
2208
            // there is at least one element: use the address of first
160
2209
            ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
160
2210
        }
160
2211
        else
0
2212
        {
0
2213
            // the address of first cannot be used: use nullptr
0
2214
            ia = std::make_shared<input_buffer_adapter>(nullptr, len);
0
2215
        }
160
2216
    }
_ZN8nlohmann6detail13input_adapterC2IPKcLi0EEET_S5_
1.64k
2186
    {
1.64k
2187
#ifndef NDEBUG
1.64k
2188
        // assertion to check that the iterator range is indeed contiguous,
1.64k
2189
        // see http://stackoverflow.com/a/35008842/266378 for more discussion
1.64k
2190
        const auto is_contiguous = std::accumulate(
1.64k
2191
                                       first, last, std::pair<bool, int>(true, 0),
1.64k
2192
                                       [&first](std::pair<bool, int> res, decltype(*first) val)
1.64k
2193
        {
1.64k
2194
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
1.64k
2195
            return res;
1.64k
2196
        }).first;
1.64k
2197
        assert(is_contiguous);
1.64k
2198
#endif
1.64k
2199
1.64k
2200
        // assertion to check that each element is 1 byte long
1.64k
2201
        static_assert(
1.64k
2202
            sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
1.64k
2203
            "each element in the iterator range must have the size of 1 byte");
1.64k
2204
1.64k
2205
        const auto len = static_cast<size_t>(std::distance(first, last));
1.64k
2206
        if (JSON_LIKELY(len > 0))
1.64k
2207
        {
1.64k
2208
            // there is at least one element: use the address of first
1.64k
2209
            ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
1.64k
2210
        }
1.64k
2211
        else
0
2212
        {
0
2213
            // the address of first cannot be used: use nullptr
0
2214
            ia = std::make_shared<input_buffer_adapter>(nullptr, len);
0
2215
        }
1.64k
2216
    }
2217
2218
    /// input adapter for array
2219
    template<class T, std::size_t N>
2220
    input_adapter(T (&array)[N])
1.64k
2221
        : input_adapter(std::begin(array), std::end(array)) {}
_ZN8nlohmann6detail13input_adapterC2IKcLj117EEERAT0__T_
548
2221
        : input_adapter(std::begin(array), std::end(array)) {}
_ZN8nlohmann6detail13input_adapterC2IKcLj10282EEERAT0__T_
548
2221
        : input_adapter(std::begin(array), std::end(array)) {}
_ZN8nlohmann6detail13input_adapterC2IKcLj10259EEERAT0__T_
548
2221
        : input_adapter(std::begin(array), std::end(array)) {}
2222
2223
    /// input adapter for contiguous container
2224
    template<class ContiguousContainer, typename
2225
             std::enable_if<not std::is_pointer<ContiguousContainer>::value and
2226
                            std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
2227
                            int>::type = 0>
2228
    input_adapter(const ContiguousContainer& c)
160
2229
        : input_adapter(std::begin(c), std::end(c)) {}
2230
2231
    operator input_adapter_t()
2.34k
2232
    {
2.34k
2233
        return ia;
2.34k
2234
    }
2235
2236
  private:
2237
    /// the actual adapter
2238
    input_adapter_t ia = nullptr;
2239
};
2240
}
2241
}
2242
2243
// #include <nlohmann/detail/input/lexer.hpp>
2244
2245
2246
#include <clocale> // localeconv
2247
#include <cstddef> // size_t
2248
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
2249
#include <cstdio> // snprintf
2250
#include <initializer_list> // initializer_list
2251
#include <string> // char_traits, string
2252
#include <vector> // vector
2253
2254
// #include <nlohmann/detail/macro_scope.hpp>
2255
2256
// #include <nlohmann/detail/input/input_adapters.hpp>
2257
2258
2259
namespace nlohmann
2260
{
2261
namespace detail
2262
{
2263
///////////
2264
// lexer //
2265
///////////
2266
2267
/*!
2268
@brief lexical analysis
2269
2270
This class organizes the lexical analysis during JSON deserialization.
2271
*/
2272
template<typename BasicJsonType>
2273
class lexer
2274
{
2275
    using number_integer_t = typename BasicJsonType::number_integer_t;
2276
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
2277
    using number_float_t = typename BasicJsonType::number_float_t;
2278
    using string_t = typename BasicJsonType::string_t;
2279
2280
  public:
2281
    /// token types for the parser
2282
    enum class token_type
2283
    {
2284
        uninitialized,    ///< indicating the scanner is uninitialized
2285
        literal_true,     ///< the `true` literal
2286
        literal_false,    ///< the `false` literal
2287
        literal_null,     ///< the `null` literal
2288
        value_string,     ///< a string -- use get_string() for actual value
2289
        value_unsigned,   ///< an unsigned integer -- use get_number_unsigned() for actual value
2290
        value_integer,    ///< a signed integer -- use get_number_integer() for actual value
2291
        value_float,      ///< an floating point number -- use get_number_float() for actual value
2292
        begin_array,      ///< the character for array begin `[`
2293
        begin_object,     ///< the character for object begin `{`
2294
        end_array,        ///< the character for array end `]`
2295
        end_object,       ///< the character for object end `}`
2296
        name_separator,   ///< the name separator `:`
2297
        value_separator,  ///< the value separator `,`
2298
        parse_error,      ///< indicating a parse error
2299
        end_of_input,     ///< indicating the end of the input buffer
2300
        literal_or_value  ///< a literal or the begin of a value (only for diagnostics)
2301
    };
2302
2303
    /// return name of values of type token_type (only used for errors)
2304
    static const char* token_type_name(const token_type t) noexcept
0
2305
    {
0
2306
        switch (t)
0
2307
        {
0
2308
            case token_type::uninitialized:
0
2309
                return "<uninitialized>";
0
2310
            case token_type::literal_true:
0
2311
                return "true literal";
0
2312
            case token_type::literal_false:
0
2313
                return "false literal";
0
2314
            case token_type::literal_null:
0
2315
                return "null literal";
0
2316
            case token_type::value_string:
0
2317
                return "string literal";
0
2318
            case lexer::token_type::value_unsigned:
0
2319
            case lexer::token_type::value_integer:
0
2320
            case lexer::token_type::value_float:
0
2321
                return "number literal";
0
2322
            case token_type::begin_array:
0
2323
                return "'['";
0
2324
            case token_type::begin_object:
0
2325
                return "'{'";
0
2326
            case token_type::end_array:
0
2327
                return "']'";
0
2328
            case token_type::end_object:
0
2329
                return "'}'";
0
2330
            case token_type::name_separator:
0
2331
                return "':'";
0
2332
            case token_type::value_separator:
0
2333
                return "','";
0
2334
            case token_type::parse_error:
0
2335
                return "<parse error>";
0
2336
            case token_type::end_of_input:
0
2337
                return "end of input";
0
2338
            case token_type::literal_or_value:
0
2339
                return "'[', '{', or a literal";
0
2340
            // LCOV_EXCL_START
0
2341
            default: // catch non-enum values
0
2342
                return "unknown token";
0
2343
                // LCOV_EXCL_STOP
0
2344
        }
0
2345
    }
2346
2347
    explicit lexer(detail::input_adapter_t&& adapter)
2.34k
2348
        : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
2349
2350
    // delete because of pointer members
2351
    lexer(const lexer&) = delete;
2352
    lexer& operator=(lexer&) = delete;
2353
2354
  private:
2355
    /////////////////////
2356
    // locales
2357
    /////////////////////
2358
2359
    /// return the locale-dependent decimal point
2360
    static char get_decimal_point() noexcept
2.34k
2361
    {
2.34k
2362
        const auto loc = localeconv();
2.34k
2363
        assert(loc != nullptr);
2.34k
2364
        return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
2.34k
2365
    }
2366
2367
    /////////////////////
2368
    // scan functions
2369
    /////////////////////
2370
2371
    /*!
2372
    @brief get codepoint from 4 hex characters following `\u`
2373
2374
    For input "\u c1 c2 c3 c4" the codepoint is:
2375
      (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
2376
    = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
2377
2378
    Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
2379
    must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
2380
    conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
2381
    between the ASCII value of the character and the desired integer value.
2382
2383
    @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
2384
            non-hex character)
2385
    */
2386
    int get_codepoint()
0
2387
    {
0
2388
        // this function only makes sense after reading `\u`
0
2389
        assert(current == 'u');
0
2390
        int codepoint = 0;
0
2391
0
2392
        const auto factors = { 12, 8, 4, 0 };
0
2393
        for (const auto factor : factors)
0
2394
        {
0
2395
            get();
0
2396
0
2397
            if (current >= '0' and current <= '9')
0
2398
            {
0
2399
                codepoint += ((current - 0x30) << factor);
0
2400
            }
0
2401
            else if (current >= 'A' and current <= 'F')
0
2402
            {
0
2403
                codepoint += ((current - 0x37) << factor);
0
2404
            }
0
2405
            else if (current >= 'a' and current <= 'f')
0
2406
            {
0
2407
                codepoint += ((current - 0x57) << factor);
0
2408
            }
0
2409
            else
0
2410
            {
0
2411
                return -1;
0
2412
            }
0
2413
        }
0
2414
0
2415
        assert(0x0000 <= codepoint and codepoint <= 0xFFFF);
0
2416
        return codepoint;
0
2417
    }
2418
2419
    /*!
2420
    @brief check if the next byte(s) are inside a given range
2421
2422
    Adds the current byte and, for each passed range, reads a new byte and
2423
    checks if it is inside the range. If a violation was detected, set up an
2424
    error message and return false. Otherwise, return true.
2425
2426
    @param[in] ranges  list of integers; interpreted as list of pairs of
2427
                       inclusive lower and upper bound, respectively
2428
2429
    @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
2430
         1, 2, or 3 pairs. This precondition is enforced by an assertion.
2431
2432
    @return true if and only if no range violation was detected
2433
    */
2434
    bool next_byte_in_range(std::initializer_list<int> ranges)
0
2435
    {
0
2436
        assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);
0
2437
        add(current);
0
2438
0
2439
        for (auto range = ranges.begin(); range != ranges.end(); ++range)
0
2440
        {
0
2441
            get();
0
2442
            if (JSON_LIKELY(*range <= current and current <= *(++range)))
0
2443
            {
0
2444
                add(current);
0
2445
            }
0
2446
            else
0
2447
            {
0
2448
                error_message = "invalid string: ill-formed UTF-8 byte";
0
2449
                return false;
0
2450
            }
0
2451
        }
0
2452
0
2453
        return true;
0
2454
    }
2455
2456
    /*!
2457
    @brief scan a string literal
2458
2459
    This function scans a string according to Sect. 7 of RFC 7159. While
2460
    scanning, bytes are escaped and copied into buffer token_buffer. Then the
2461
    function returns successfully, token_buffer is *not* null-terminated (as it
2462
    may contain \0 bytes), and token_buffer.size() is the number of bytes in the
2463
    string.
2464
2465
    @return token_type::value_string if string could be successfully scanned,
2466
            token_type::parse_error otherwise
2467
2468
    @note In case of errors, variable error_message contains a textual
2469
          description.
2470
    */
2471
    token_type scan_string()
851k
2472
    {
851k
2473
        // reset token_buffer (ignore opening quote)
851k
2474
        reset();
851k
2475
851k
2476
        // we entered the function by reading an open quote
851k
2477
        assert(current == '\"');
851k
2478
7.54M
2479
        while (true)
7.54M
2480
        {
7.54M
2481
            // get next character
6.69M
2482
            switch (get())
6.69M
2483
            {
6.69M
2484
                // end of file while parsing string
0
2485
                case std::char_traits<char>::eof():
0
2486
                {
0
2487
                    error_message = "invalid string: missing closing quote";
0
2488
                    return token_type::parse_error;
0
2489
                }
0
2490
0
2491
                // closing quote
851k
2492
                case '\"':
851k
2493
                {
851k
2494
                    return token_type::value_string;
0
2495
                }
0
2496
0
2497
                // escapes
0
2498
                case '\\':
0
2499
                {
0
2500
                    switch (get())
0
2501
                    {
0
2502
                        // quotation mark
0
2503
                        case '\"':
0
2504
                            add('\"');
0
2505
                            break;
0
2506
                        // reverse solidus
0
2507
                        case '\\':
0
2508
                            add('\\');
0
2509
                            break;
0
2510
                        // solidus
0
2511
                        case '/':
0
2512
                            add('/');
0
2513
                            break;
0
2514
                        // backspace
0
2515
                        case 'b':
0
2516
                            add('\b');
0
2517
                            break;
0
2518
                        // form feed
0
2519
                        case 'f':
0
2520
                            add('\f');
0
2521
                            break;
0
2522
                        // line feed
0
2523
                        case 'n':
0
2524
                            add('\n');
0
2525
                            break;
0
2526
                        // carriage return
0
2527
                        case 'r':
0
2528
                            add('\r');
0
2529
                            break;
0
2530
                        // tab
0
2531
                        case 't':
0
2532
                            add('\t');
0
2533
                            break;
0
2534
0
2535
                        // unicode escapes
0
2536
                        case 'u':
0
2537
                        {
0
2538
                            const int codepoint1 = get_codepoint();
0
2539
                            int codepoint = codepoint1; // start with codepoint1
0
2540
0
2541
                            if (JSON_UNLIKELY(codepoint1 == -1))
0
2542
                            {
0
2543
                                error_message = "invalid string: '\\u' must be followed by 4 hex digits";
0
2544
                                return token_type::parse_error;
0
2545
                            }
0
2546
0
2547
                            // check if code point is a high surrogate
0
2548
                            if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)
0
2549
                            {
0
2550
                                // expect next \uxxxx entry
0
2551
                                if (JSON_LIKELY(get() == '\\' and get() == 'u'))
0
2552
                                {
0
2553
                                    const int codepoint2 = get_codepoint();
0
2554
0
2555
                                    if (JSON_UNLIKELY(codepoint2 == -1))
0
2556
                                    {
0
2557
                                        error_message = "invalid string: '\\u' must be followed by 4 hex digits";
0
2558
                                        return token_type::parse_error;
0
2559
                                    }
0
2560
0
2561
                                    // check if codepoint2 is a low surrogate
0
2562
                                    if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
0
2563
                                    {
0
2564
                                        // overwrite codepoint
0
2565
                                        codepoint =
0
2566
                                            // high surrogate occupies the most significant 22 bits
0
2567
                                            (codepoint1 << 10)
0
2568
                                            // low surrogate occupies the least significant 15 bits
0
2569
                                            + codepoint2
0
2570
                                            // there is still the 0xD800, 0xDC00 and 0x10000 noise
0
2571
                                            // in the result so we have to subtract with:
0
2572
                                            // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
0
2573
                                            - 0x35FDC00;
0
2574
                                    }
0
2575
                                    else
0
2576
                                    {
0
2577
                                        error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
0
2578
                                        return token_type::parse_error;
0
2579
                                    }
0
2580
                                }
0
2581
                                else
0
2582
                                {
0
2583
                                    error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
0
2584
                                    return token_type::parse_error;
0
2585
                                }
0
2586
                            }
0
2587
                            else
0
2588
                            {
0
2589
                                if (JSON_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
0
2590
                                {
0
2591
                                    error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
0
2592
                                    return token_type::parse_error;
0
2593
                                }
0
2594
                            }
0
2595
0
2596
                            // result of the above calculation yields a proper codepoint
0
2597
                            assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
0
2598
0
2599
                            // translate codepoint into bytes
0
2600
                            if (codepoint < 0x80)
0
2601
                            {
0
2602
                                // 1-byte characters: 0xxxxxxx (ASCII)
0
2603
                                add(codepoint);
0
2604
                            }
0
2605
                            else if (codepoint <= 0x7FF)
0
2606
                            {
0
2607
                                // 2-byte characters: 110xxxxx 10xxxxxx
0
2608
                                add(0xC0 | (codepoint >> 6));
0
2609
                                add(0x80 | (codepoint & 0x3F));
0
2610
                            }
0
2611
                            else if (codepoint <= 0xFFFF)
0
2612
                            {
0
2613
                                // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
0
2614
                                add(0xE0 | (codepoint >> 12));
0
2615
                                add(0x80 | ((codepoint >> 6) & 0x3F));
0
2616
                                add(0x80 | (codepoint & 0x3F));
0
2617
                            }
0
2618
                            else
0
2619
                            {
0
2620
                                // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0
2621
                                add(0xF0 | (codepoint >> 18));
0
2622
                                add(0x80 | ((codepoint >> 12) & 0x3F));
0
2623
                                add(0x80 | ((codepoint >> 6) & 0x3F));
0
2624
                                add(0x80 | (codepoint & 0x3F));
0
2625
                            }
0
2626
0
2627
                            break;
0
2628
                        }
0
2629
0
2630
                        // other characters after escape
0
2631
                        default:
0
2632
                            error_message = "invalid string: forbidden character after backslash";
0
2633
                            return token_type::parse_error;
0
2634
                    }
0
2635
0
2636
                    break;
0
2637
                }
0
2638
0
2639
                // invalid control characters
0
2640
                case 0x00:
0
2641
                case 0x01:
0
2642
                case 0x02:
0
2643
                case 0x03:
0
2644
                case 0x04:
0
2645
                case 0x05:
0
2646
                case 0x06:
0
2647
                case 0x07:
0
2648
                case 0x08:
0
2649
                case 0x09:
0
2650
                case 0x0A:
0
2651
                case 0x0B:
0
2652
                case 0x0C:
0
2653
                case 0x0D:
0
2654
                case 0x0E:
0
2655
                case 0x0F:
0
2656
                case 0x10:
0
2657
                case 0x11:
0
2658
                case 0x12:
0
2659
                case 0x13:
0
2660
                case 0x14:
0
2661
                case 0x15:
0
2662
                case 0x16:
0
2663
                case 0x17:
0
2664
                case 0x18:
0
2665
                case 0x19:
0
2666
                case 0x1A:
0
2667
                case 0x1B:
0
2668
                case 0x1C:
0
2669
                case 0x1D:
0
2670
                case 0x1E:
0
2671
                case 0x1F:
0
2672
                {
0
2673
                    error_message = "invalid string: control character must be escaped";
0
2674
                    return token_type::parse_error;
0
2675
                }
0
2676
0
2677
                // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
6.69M
2678
                case 0x20:
6.69M
2679
                case 0x21:
6.69M
2680
                case 0x23:
6.69M
2681
                case 0x24:
6.69M
2682
                case 0x25:
6.69M
2683
                case 0x26:
6.69M
2684
                case 0x27:
6.69M
2685
                case 0x28:
6.69M
2686
                case 0x29:
6.69M
2687
                case 0x2A:
6.69M
2688
                case 0x2B:
6.69M
2689
                case 0x2C:
6.69M
2690
                case 0x2D:
6.69M
2691
                case 0x2E:
6.69M
2692
                case 0x2F:
6.69M
2693
                case 0x30:
6.69M
2694
                case 0x31:
6.69M
2695
                case 0x32:
6.69M
2696
                case 0x33:
6.69M
2697
                case 0x34:
6.69M
2698
                case 0x35:
6.69M
2699
                case 0x36:
6.69M
2700
                case 0x37:
6.69M
2701
                case 0x38:
6.69M
2702
                case 0x39:
6.69M
2703
                case 0x3A:
6.69M
2704
                case 0x3B:
6.69M
2705
                case 0x3C:
6.69M
2706
                case 0x3D:
6.69M
2707
                case 0x3E:
6.69M
2708
                case 0x3F:
6.69M
2709
                case 0x40:
6.69M
2710
                case 0x41:
6.69M
2711
                case 0x42:
6.69M
2712
                case 0x43:
6.69M
2713
                case 0x44:
6.69M
2714
                case 0x45:
6.69M
2715
                case 0x46:
6.69M
2716
                case 0x47:
6.69M
2717
                case 0x48:
6.69M
2718
                case 0x49:
6.69M
2719
                case 0x4A:
6.69M
2720
                case 0x4B:
6.69M
2721
                case 0x4C:
6.69M
2722
                case 0x4D:
6.69M
2723
                case 0x4E:
6.69M
2724
                case 0x4F:
6.69M
2725
                case 0x50:
6.69M
2726
                case 0x51:
6.69M
2727
                case 0x52:
6.69M
2728
                case 0x53:
6.69M
2729
                case 0x54:
6.69M
2730
                case 0x55:
6.69M
2731
                case 0x56:
6.69M
2732
                case 0x57:
6.69M
2733
                case 0x58:
6.69M
2734
                case 0x59:
6.69M
2735
                case 0x5A:
6.69M
2736
                case 0x5B:
6.69M
2737
                case 0x5D:
6.69M
2738
                case 0x5E:
6.69M
2739
                case 0x5F:
6.69M
2740
                case 0x60:
6.69M
2741
                case 0x61:
6.69M
2742
                case 0x62:
6.69M
2743
                case 0x63:
6.69M
2744
                case 0x64:
6.69M
2745
                case 0x65:
6.69M
2746
                case 0x66:
6.69M
2747
                case 0x67:
6.69M
2748
                case 0x68:
6.69M
2749
                case 0x69:
6.69M
2750
                case 0x6A:
6.69M
2751
                case 0x6B:
6.69M
2752
                case 0x6C:
6.69M
2753
                case 0x6D:
6.69M
2754
                case 0x6E:
6.69M
2755
                case 0x6F:
6.69M
2756
                case 0x70:
6.69M
2757
                case 0x71:
6.69M
2758
                case 0x72:
6.69M
2759
                case 0x73:
6.69M
2760
                case 0x74:
6.69M
2761
                case 0x75:
6.69M
2762
                case 0x76:
6.69M
2763
                case 0x77:
6.69M
2764
                case 0x78:
6.69M
2765
                case 0x79:
6.69M
2766
                case 0x7A:
6.69M
2767
                case 0x7B:
6.69M
2768
                case 0x7C:
6.69M
2769
                case 0x7D:
6.69M
2770
                case 0x7E:
6.69M
2771
                case 0x7F:
6.69M
2772
                {
6.69M
2773
                    add(current);
6.69M
2774
                    break;
6.69M
2775
                }
6.69M
2776
6.69M
2777
                // U+0080..U+07FF: bytes C2..DF 80..BF
0
2778
                case 0xC2:
0
2779
                case 0xC3:
0
2780
                case 0xC4:
0
2781
                case 0xC5:
0
2782
                case 0xC6:
0
2783
                case 0xC7:
0
2784
                case 0xC8:
0
2785
                case 0xC9:
0
2786
                case 0xCA:
0
2787
                case 0xCB:
0
2788
                case 0xCC:
0
2789
                case 0xCD:
0
2790
                case 0xCE:
0
2791
                case 0xCF:
0
2792
                case 0xD0:
0
2793
                case 0xD1:
0
2794
                case 0xD2:
0
2795
                case 0xD3:
0
2796
                case 0xD4:
0
2797
                case 0xD5:
0
2798
                case 0xD6:
0
2799
                case 0xD7:
0
2800
                case 0xD8:
0
2801
                case 0xD9:
0
2802
                case 0xDA:
0
2803
                case 0xDB:
0
2804
                case 0xDC:
0
2805
                case 0xDD:
0
2806
                case 0xDE:
0
2807
                case 0xDF:
0
2808
                {
0
2809
                    if (JSON_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
0
2810
                    {
0
2811
                        return token_type::parse_error;
0
2812
                    }
0
2813
                    break;
0
2814
                }
0
2815
0
2816
                // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
0
2817
                case 0xE0:
0
2818
                {
0
2819
                    if (JSON_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
0
2820
                    {
0
2821
                        return token_type::parse_error;
0
2822
                    }
0
2823
                    break;
0
2824
                }
0
2825
0
2826
                // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
0
2827
                // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
0
2828
                case 0xE1:
0
2829
                case 0xE2:
0
2830
                case 0xE3:
0
2831
                case 0xE4:
0
2832
                case 0xE5:
0
2833
                case 0xE6:
0
2834
                case 0xE7:
0
2835
                case 0xE8:
0
2836
                case 0xE9:
0
2837
                case 0xEA:
0
2838
                case 0xEB:
0
2839
                case 0xEC:
0
2840
                case 0xEE:
0
2841
                case 0xEF:
0
2842
                {
0
2843
                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
0
2844
                    {
0
2845
                        return token_type::parse_error;
0
2846
                    }
0
2847
                    break;
0
2848
                }
0
2849
0
2850
                // U+D000..U+D7FF: bytes ED 80..9F 80..BF
0
2851
                case 0xED:
0
2852
                {
0
2853
                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
0
2854
                    {
0
2855
                        return token_type::parse_error;
0
2856
                    }
0
2857
                    break;
0
2858
                }
0
2859
0
2860
                // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
0
2861
                case 0xF0:
0
2862
                {
0
2863
                    if (JSON_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
0
2864
                    {
0
2865
                        return token_type::parse_error;
0
2866
                    }
0
2867
                    break;
0
2868
                }
0
2869
0
2870
                // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
0
2871
                case 0xF1:
0
2872
                case 0xF2:
0
2873
                case 0xF3:
0
2874
                {
0
2875
                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
0
2876
                    {
0
2877
                        return token_type::parse_error;
0
2878
                    }
0
2879
                    break;
0
2880
                }
0
2881
0
2882
                // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
0
2883
                case 0xF4:
0
2884
                {
0
2885
                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
0
2886
                    {
0
2887
                        return token_type::parse_error;
0
2888
                    }
0
2889
                    break;
0
2890
                }
0
2891
0
2892
                // remaining bytes (80..C1 and F5..FF) are ill-formed
0
2893
                default:
0
2894
                {
0
2895
                    error_message = "invalid string: ill-formed UTF-8 byte";
0
2896
                    return token_type::parse_error;
0
2897
                }
6.69M
2898
            }
7.54M
2899
        }
851k
2900
    }
2901
2902
    static void strtof(float& f, const char* str, char** endptr) noexcept
2903
    {
2904
        f = std::strtof(str, endptr);
2905
    }
2906
2907
    static void strtof(double& f, const char* str, char** endptr) noexcept
158k
2908
    {
158k
2909
        f = std::strtod(str, endptr);
158k
2910
    }
2911
2912
    static void strtof(long double& f, const char* str, char** endptr) noexcept
2913
    {
2914
        f = std::strtold(str, endptr);
2915
    }
2916
2917
    /*!
2918
    @brief scan a number literal
2919
2920
    This function scans a string according to Sect. 6 of RFC 7159.
2921
2922
    The function is realized with a deterministic finite state machine derived
2923
    from the grammar described in RFC 7159. Starting in state "init", the
2924
    input is read and used to determined the next state. Only state "done"
2925
    accepts the number. State "error" is a trap state to model errors. In the
2926
    table below, "anything" means any character but the ones listed before.
2927
2928
    state    | 0        | 1-9      | e E      | +       | -       | .        | anything
2929
    ---------|----------|----------|----------|---------|---------|----------|-----------
2930
    init     | zero     | any1     | [error]  | [error] | minus   | [error]  | [error]
2931
    minus    | zero     | any1     | [error]  | [error] | [error] | [error]  | [error]
2932
    zero     | done     | done     | exponent | done    | done    | decimal1 | done
2933
    any1     | any1     | any1     | exponent | done    | done    | decimal1 | done
2934
    decimal1 | decimal2 | [error]  | [error]  | [error] | [error] | [error]  | [error]
2935
    decimal2 | decimal2 | decimal2 | exponent | done    | done    | done     | done
2936
    exponent | any2     | any2     | [error]  | sign    | sign    | [error]  | [error]
2937
    sign     | any2     | any2     | [error]  | [error] | [error] | [error]  | [error]
2938
    any2     | any2     | any2     | done     | done    | done    | done     | done
2939
2940
    The state machine is realized with one label per state (prefixed with
2941
    "scan_number_") and `goto` statements between them. The state machine
2942
    contains cycles, but any cycle can be left when EOF is read. Therefore,
2943
    the function is guaranteed to terminate.
2944
2945
    During scanning, the read bytes are stored in token_buffer. This string is
2946
    then converted to a signed integer, an unsigned integer, or a
2947
    floating-point number.
2948
2949
    @return token_type::value_unsigned, token_type::value_integer, or
2950
            token_type::value_float if number could be successfully scanned,
2951
            token_type::parse_error otherwise
2952
2953
    @note The scanner is independent of the current locale. Internally, the
2954
          locale's decimal point is used instead of `.` to work with the
2955
          locale-dependent converters.
2956
    */
2957
    token_type scan_number()
396k
2958
    {
396k
2959
        // reset token_buffer to store the number's bytes
396k
2960
        reset();
396k
2961
396k
2962
        // the type of the parsed number; initially set to unsigned; will be
396k
2963
        // changed if minus sign, decimal point or exponent is read
396k
2964
        token_type number_type = token_type::value_unsigned;
396k
2965
396k
2966
        // state (init): we just found out we need to scan a number
0
2967
        switch (current)
0
2968
        {
25.3k
2969
            case '-':
25.3k
2970
            {
25.3k
2971
                add(current);
25.3k
2972
                goto scan_number_minus;
25.3k
2973
            }
25.3k
2974
53.3k
2975
            case '0':
53.3k
2976
            {
53.3k
2977
                add(current);
53.3k
2978
                goto scan_number_zero;
25.3k
2979
            }
25.3k
2980
317k
2981
            case '1':
317k
2982
            case '2':
317k
2983
            case '3':
317k
2984
            case '4':
317k
2985
            case '5':
317k
2986
            case '6':
317k
2987
            case '7':
317k
2988
            case '8':
317k
2989
            case '9':
317k
2990
            {
317k
2991
                add(current);
317k
2992
                goto scan_number_any1;
317k
2993
            }
317k
2994
317k
2995
            // LCOV_EXCL_START
0
2996
            default:
0
2997
            {
0
2998
                // all other characters are rejected outside scan_number()
0
2999
                assert(false);
0
3000
            }
0
3001
                // LCOV_EXCL_STOP
0
3002
        }
396k
3003
25.3k
3004
scan_number_minus:
25.3k
3005
        // state: we just parsed a leading minus sign
25.3k
3006
        number_type = token_type::value_integer;
0
3007
        switch (get())
0
3008
        {
0
3009
            case '0':
0
3010
            {
0
3011
                add(current);
0
3012
                goto scan_number_zero;
0
3013
            }
0
3014
25.3k
3015
            case '1':
25.3k
3016
            case '2':
25.3k
3017
            case '3':
25.3k
3018
            case '4':
25.3k
3019
            case '5':
25.3k
3020
            case '6':
25.3k
3021
            case '7':
25.3k
3022
            case '8':
25.3k
3023
            case '9':
25.3k
3024
            {
25.3k
3025
                add(current);
25.3k
3026
                goto scan_number_any1;
25.3k
3027
            }
25.3k
3028
0
3029
            default:
0
3030
            {
0
3031
                error_message = "invalid number; expected digit after '-'";
0
3032
                return token_type::parse_error;
25.3k
3033
            }
0
3034
        }
25.3k
3035
53.3k
3036
scan_number_zero:
53.3k
3037
        // state: we just parse a zero (maybe with a leading minus sign)
0
3038
        switch (get())
0
3039
        {
548
3040
            case '.':
548
3041
            {
548
3042
                add(decimal_point_char);
548
3043
                goto scan_number_decimal1;
548
3044
            }
548
3045
0
3046
            case 'e':
0
3047
            case 'E':
0
3048
            {
0
3049
                add(current);
0
3050
                goto scan_number_exponent;
0
3051
            }
0
3052
52.8k
3053
            default:
52.8k
3054
                goto scan_number_done;
0
3055
        }
53.3k
3056
1.16M
3057
scan_number_any1:
1.16M
3058
        // state: we just parsed a number 0-9 (maybe with a leading minus sign)
0
3059
        switch (get())
0
3060
        {
824k
3061
            case '0':
824k
3062
            case '1':
824k
3063
            case '2':
824k
3064
            case '3':
824k
3065
            case '4':
824k
3066
            case '5':
824k
3067
            case '6':
824k
3068
            case '7':
824k
3069
            case '8':
824k
3070
            case '9':
824k
3071
            {
824k
3072
                add(current);
824k
3073
                goto scan_number_any1;
824k
3074
            }
824k
3075
157k
3076
            case '.':
157k
3077
            {
157k
3078
                add(decimal_point_char);
157k
3079
                goto scan_number_decimal1;
824k
3080
            }
824k
3081
0
3082
            case 'e':
0
3083
            case 'E':
0
3084
            {
0
3085
                add(current);
0
3086
                goto scan_number_exponent;
0
3087
            }
0
3088
184k
3089
            default:
184k
3090
                goto scan_number_done;
0
3091
        }
1.16M
3092
158k
3093
scan_number_decimal1:
158k
3094
        // state: we just parsed a decimal point
158k
3095
        number_type = token_type::value_float;
0
3096
        switch (get())
0
3097
        {
158k
3098
            case '0':
158k
3099
            case '1':
158k
3100
            case '2':
158k
3101
            case '3':
158k
3102
            case '4':
158k
3103
            case '5':
158k
3104
            case '6':
158k
3105
            case '7':
158k
3106
            case '8':
158k
3107
            case '9':
158k
3108
            {
158k
3109
                add(current);
158k
3110
                goto scan_number_decimal2;
158k
3111
            }
158k
3112
0
3113
            default:
0
3114
            {
0
3115
                error_message = "invalid number; expected digit after '.'";
0
3116
                return token_type::parse_error;
158k
3117
            }
0
3118
        }
158k
3119
677k
3120
scan_number_decimal2:
677k
3121
        // we just parsed at least one number after a decimal point
0
3122
        switch (get())
0
3123
        {
519k
3124
            case '0':
519k
3125
            case '1':
519k
3126
            case '2':
519k
3127
            case '3':
519k
3128
            case '4':
519k
3129
            case '5':
519k
3130
            case '6':
519k
3131
            case '7':
519k
3132
            case '8':
519k
3133
            case '9':
519k
3134
            {
519k
3135
                add(current);
519k
3136
                goto scan_number_decimal2;
519k
3137
            }
519k
3138
0
3139
            case 'e':
0
3140
            case 'E':
0
3141
            {
0
3142
                add(current);
0
3143
                goto scan_number_exponent;
0
3144
            }
0
3145
158k
3146
            default:
158k
3147
                goto scan_number_done;
0
3148
        }
677k
3149
0
3150
scan_number_exponent:
0
3151
        // we just parsed an exponent
0
3152
        number_type = token_type::value_float;
0
3153
        switch (get())
0
3154
        {
0
3155
            case '+':
0
3156
            case '-':
0
3157
            {
0
3158
                add(current);
0
3159
                goto scan_number_sign;
0
3160
            }
0
3161
0
3162
            case '0':
0
3163
            case '1':
0
3164
            case '2':
0
3165
            case '3':
0
3166
            case '4':
0
3167
            case '5':
0
3168
            case '6':
0
3169
            case '7':
0
3170
            case '8':
0
3171
            case '9':
0
3172
            {
0
3173
                add(current);
0
3174
                goto scan_number_any2;
0
3175
            }
0
3176
0
3177
            default:
0
3178
            {
0
3179
                error_message =
0
3180
                    "invalid number; expected '+', '-', or digit after exponent";
0
3181
                return token_type::parse_error;
0
3182
            }
0
3183
        }
0
3184
0
3185
scan_number_sign:
0
3186
        // we just parsed an exponent sign
0
3187
        switch (get())
0
3188
        {
0
3189
            case '0':
0
3190
            case '1':
0
3191
            case '2':
0
3192
            case '3':
0
3193
            case '4':
0
3194
            case '5':
0
3195
            case '6':
0
3196
            case '7':
0
3197
            case '8':
0
3198
            case '9':
0
3199
            {
0
3200
                add(current);
0
3201
                goto scan_number_any2;
0
3202
            }
0
3203
0
3204
            default:
0
3205
            {
0
3206
                error_message = "invalid number; expected digit after exponent sign";
0
3207
                return token_type::parse_error;
0
3208
            }
0
3209
        }
0
3210
0
3211
scan_number_any2:
0
3212
        // we just parsed a number after the exponent or exponent sign
0
3213
        switch (get())
0
3214
        {
0
3215
            case '0':
0
3216
            case '1':
0
3217
            case '2':
0
3218
            case '3':
0
3219
            case '4':
0
3220
            case '5':
0
3221
            case '6':
0
3222
            case '7':
0
3223
            case '8':
0
3224
            case '9':
0
3225
            {
0
3226
                add(current);
0
3227
                goto scan_number_any2;
0
3228
            }
0
3229
0
3230
            default:
0
3231
                goto scan_number_done;
0
3232
        }
0
3233
396k
3234
scan_number_done:
396k
3235
        // unget the character after the number (we only read it to know that
396k
3236
        // we are done scanning a number)
396k
3237
        unget();
396k
3238
396k
3239
        char* endptr = nullptr;
396k
3240
        errno = 0;
396k
3241
396k
3242
        // try to parse integers first and fall back to floats
396k
3243
        if (number_type == token_type::value_unsigned)
212k
3244
        {
212k
3245
            const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
212k
3246
212k
3247
            // we checked the number format before
212k
3248
            assert(endptr == token_buffer.data() + token_buffer.size());
212k
3249
212k
3250
            if (errno == 0)
212k
3251
            {
212k
3252
                value_unsigned = static_cast<number_unsigned_t>(x);
212k
3253
                if (value_unsigned == x)
212k
3254
                {
212k
3255
                    return token_type::value_unsigned;
212k
3256
                }
212k
3257
            }
212k
3258
        }
183k
3259
        else if (number_type == token_type::value_integer)
25.3k
3260
        {
25.3k
3261
            const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
25.3k
3262
25.3k
3263
            // we checked the number format before
25.3k
3264
            assert(endptr == token_buffer.data() + token_buffer.size());
25.3k
3265
25.3k
3266
            if (errno == 0)
25.3k
3267
            {
25.3k
3268
                value_integer = static_cast<number_integer_t>(x);
25.3k
3269
                if (value_integer == x)
25.3k
3270
                {
25.3k
3271
                    return token_type::value_integer;
25.3k
3272
                }
25.3k
3273
            }
25.3k
3274
        }
396k
3275
396k
3276
        // this code is reached if we parse a floating-point number or if an
396k
3277
        // integer conversion above failed
158k
3278
        strtof(value_float, token_buffer.data(), &endptr);
158k
3279
158k
3280
        // we checked the number format before
158k
3281
        assert(endptr == token_buffer.data() + token_buffer.size());
158k
3282
158k
3283
        return token_type::value_float;
396k
3284
    }
3285
3286
    /*!
3287
    @param[in] literal_text  the literal text to expect
3288
    @param[in] length        the length of the passed literal text
3289
    @param[in] return_type   the token type to return on success
3290
    */
3291
    token_type scan_literal(const char* literal_text, const std::size_t length,
3292
                            token_type return_type)
2.77k
3293
    {
2.77k
3294
        assert(current == literal_text[0]);
11.1k
3295
        for (std::size_t i = 1; i < length; ++i)
8.32k
3296
        {
8.32k
3297
            if (JSON_UNLIKELY(get() != literal_text[i]))
0
3298
            {
0
3299
                error_message = "invalid literal";
0
3300
                return token_type::parse_error;
0
3301
            }
8.32k
3302
        }
2.77k
3303
        return return_type;
2.77k
3304
    }
3305
3306
    /////////////////////
3307
    // input management
3308
    /////////////////////
3309
3310
    /// reset token_buffer; current character is beginning of token
3311
    void reset() noexcept
1.24M
3312
    {
1.24M
3313
        token_buffer.clear();
1.24M
3314
        token_string.clear();
1.24M
3315
        token_string.push_back(std::char_traits<char>::to_char_type(current));
1.24M
3316
    }
3317
3318
    /*
3319
    @brief get next character from the input
3320
3321
    This function provides the interface to the used input adapter. It does
3322
    not throw in case the input reached EOF, but returns a
3323
    `std::char_traits<char>::eof()` in that case.  Stores the scanned characters
3324
    for use in error messages.
3325
3326
    @return character read from the input
3327
    */
3328
    std::char_traits<char>::int_type get()
12.9M
3329
    {
12.9M
3330
        ++chars_read;
12.9M
3331
        if (next_unget)
398k
3332
        {
398k
3333
            // just reset the next_unget variable and work with current
398k
3334
            next_unget = false;
398k
3335
        }
12.9M
3336
        else
12.5M
3337
        {
12.5M
3338
            current = ia->get_character();
12.5M
3339
        }
12.9M
3340
12.9M
3341
        if (JSON_LIKELY(current != std::char_traits<char>::eof()))
12.9M
3342
        {
12.9M
3343
            token_string.push_back(std::char_traits<char>::to_char_type(current));
12.9M
3344
        }
12.9M
3345
        return current;
12.9M
3346
    }
3347
3348
    /*!
3349
    @brief unget current character (read it again on next get)
3350
3351
    We implement unget by setting variable next_unget to true. The input is not
3352
    changed - we just simulate ungetting by modifying chars_read and
3353
    token_string. The next call to get() will behave as if the unget character
3354
    is read again.
3355
    */
3356
    void unget()
398k
3357
    {
398k
3358
        next_unget = true;
398k
3359
        --chars_read;
398k
3360
        if (JSON_LIKELY(current != std::char_traits<char>::eof()))
398k
3361
        {
398k
3362
            assert(token_string.size() != 0);
398k
3363
            token_string.pop_back();
398k
3364
        }
398k
3365
    }
3366
3367
    /// add a character to token_buffer
3368
    void add(int c)
8.77M
3369
    {
8.77M
3370
        token_buffer.push_back(std::char_traits<char>::to_char_type(c));
8.77M
3371
    }
3372
3373
  public:
3374
    /////////////////////
3375
    // value getters
3376
    /////////////////////
3377
3378
    /// return integer value
3379
    constexpr number_integer_t get_number_integer() const noexcept
25.3k
3380
    {
25.3k
3381
        return value_integer;
25.3k
3382
    }
3383
3384
    /// return unsigned integer value
3385
    constexpr number_unsigned_t get_number_unsigned() const noexcept
212k
3386
    {
212k
3387
        return value_unsigned;
212k
3388
    }
3389
3390
    /// return floating-point value
3391
    constexpr number_float_t get_number_float() const noexcept
158k
3392
    {
158k
3393
        return value_float;
158k
3394
    }
3395
3396
    /// return current string value (implicitly resets the token; useful only once)
3397
    string_t& get_string()
1.01M
3398
    {
1.01M
3399
        return token_buffer;
1.01M
3400
    }
3401
3402
    /////////////////////
3403
    // diagnostics
3404
    /////////////////////
3405
3406
    /// return position of last read token
3407
    constexpr std::size_t get_position() const noexcept
0
3408
    {
0
3409
        return chars_read;
0
3410
    }
3411
3412
    /// return the last read token (for errors only).  Will never contain EOF
3413
    /// (an arbitrary value that is not a valid char value, often -1), because
3414
    /// 255 may legitimately occur.  May contain NUL, which should be escaped.
3415
    std::string get_token_string() const
0
3416
    {
0
3417
        // escape control characters
0
3418
        std::string result;
0
3419
        for (const auto c : token_string)
0
3420
        {
0
3421
            if ('\x00' <= c and c <= '\x1F')
0
3422
            {
0
3423
                // escape control characters
0
3424
                char cs[9];
0
3425
                snprintf(cs, 9, "<U+%.4X>", static_cast<unsigned char>(c));
0
3426
                result += cs;
0
3427
            }
0
3428
            else
0
3429
            {
0
3430
                // add character as is
0
3431
                result.push_back(c);
0
3432
            }
0
3433
        }
0
3434
0
3435
        return result;
0
3436
    }
3437
3438
    /// return syntax error message
3439
    constexpr const char* get_error_message() const noexcept
0
3440
    {
0
3441
        return error_message;
0
3442
    }
3443
3444
    /////////////////////
3445
    // actual scanner
3446
    /////////////////////
3447
3448
    /*!
3449
    @brief skip the UTF-8 byte order mark
3450
    @return true iff there is no BOM or the correct BOM has been skipped
3451
    */
3452
    bool skip_bom()
2.34k
3453
    {
2.34k
3454
        if (get() == 0xEF)
0
3455
        {
0
3456
            if (get() == 0xBB and get() == 0xBF)
0
3457
            {
0
3458
                // we completely parsed the BOM
0
3459
                return true;
0
3460
            }
0
3461
            else
0
3462
            {
0
3463
                // after reading 0xEF, an unexpected character followed
0
3464
                return false;
0
3465
            }
0
3466
        }
2.34k
3467
        else
2.34k
3468
        {
2.34k
3469
            // the first character is not the beginning of the BOM; unget it to
2.34k
3470
            // process is later
2.34k
3471
            unget();
2.34k
3472
            return true;
2.34k
3473
        }
2.34k
3474
    }
3475
3476
    token_type scan()
2.78M
3477
    {
2.78M
3478
        // initially, skip the BOM
2.78M
3479
        if (chars_read == 0 and not skip_bom())
0
3480
        {
0
3481
            error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
0
3482
            return token_type::parse_error;
0
3483
        }
2.78M
3484
2.78M
3485
        // read next character and ignore whitespace
2.78M
3486
        do
3.30M
3487
        {
3.30M
3488
            get();
3.30M
3489
        }
3.30M
3490
        while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
2.78M
3491
0
3492
        switch (current)
0
3493
        {
0
3494
            // structural characters
1.66k
3495
            case '[':
1.66k
3496
                return token_type::begin_array;
1.66k
3497
            case ']':
1.66k
3498
                return token_type::end_array;
140k
3499
            case '{':
140k
3500
                return token_type::begin_object;
140k
3501
            case '}':
140k
3502
                return token_type::end_object;
681k
3503
            case ':':
681k
3504
                return token_type::name_separator;
566k
3505
            case ',':
566k
3506
                return token_type::value_separator;
1.66k
3507
1.66k
3508
            // literals
1.66k
3509
            case 't':
1.66k
3510
                return scan_literal("true", 4, token_type::literal_true);
0
3511
            case 'f':
0
3512
                return scan_literal("false", 5, token_type::literal_false);
1.11k
3513
            case 'n':
1.11k
3514
                return scan_literal("null", 4, token_type::literal_null);
1.66k
3515
1.66k
3516
            // string
851k
3517
            case '\"':
851k
3518
                return scan_string();
1.66k
3519
1.66k
3520
            // number
396k
3521
            case '-':
396k
3522
            case '0':
396k
3523
            case '1':
396k
3524
            case '2':
396k
3525
            case '3':
396k
3526
            case '4':
396k
3527
            case '5':
396k
3528
            case '6':
396k
3529
            case '7':
396k
3530
            case '8':
396k
3531
            case '9':
396k
3532
                return scan_number();
396k
3533
396k
3534
            // end of input (the null byte is needed when parsing from
396k
3535
            // string literals)
1.80k
3536
            case '\0':
1.80k
3537
            case std::char_traits<char>::eof():
1.80k
3538
                return token_type::end_of_input;
1.80k
3539
1.80k
3540
            // error
0
3541
            default:
0
3542
                error_message = "invalid literal";
0
3543
                return token_type::parse_error;
0
3544
        }
2.78M
3545
    }
3546
3547
  private:
3548
    /// input adapter
3549
    detail::input_adapter_t ia = nullptr;
3550
3551
    /// the current character
3552
    std::char_traits<char>::int_type current = std::char_traits<char>::eof();
3553
3554
    /// whether the next get() call should just return current
3555
    bool next_unget = false;
3556
3557
    /// the number of characters read
3558
    std::size_t chars_read = 0;
3559
3560
    /// raw input token string (for error messages)
3561
    std::vector<char> token_string {};
3562
3563
    /// buffer for variable-length tokens (numbers, strings)
3564
    string_t token_buffer {};
3565
3566
    /// a description of occurred lexer errors
3567
    const char* error_message = "";
3568
3569
    // number values
3570
    number_integer_t value_integer = 0;
3571
    number_unsigned_t value_unsigned = 0;
3572
    number_float_t value_float = 0;
3573
3574
    /// the decimal point
3575
    const char decimal_point_char = '.';
3576
};
3577
}
3578
}
3579
3580
// #include <nlohmann/detail/input/parser.hpp>
3581
3582
3583
#include <cassert> // assert
3584
#include <cmath> // isfinite
3585
#include <cstdint> // uint8_t
3586
#include <functional> // function
3587
#include <string> // string
3588
#include <utility> // move
3589
3590
// #include <nlohmann/detail/exceptions.hpp>
3591
3592
// #include <nlohmann/detail/macro_scope.hpp>
3593
3594
// #include <nlohmann/detail/meta/is_sax.hpp>
3595
3596
3597
#include <cstdint> // size_t
3598
#include <utility> // declval
3599
3600
// #include <nlohmann/detail/meta/detected.hpp>
3601
3602
// #include <nlohmann/detail/meta/type_traits.hpp>
3603
3604
3605
namespace nlohmann
3606
{
3607
namespace detail
3608
{
3609
template <typename T>
3610
using null_function_t = decltype(std::declval<T&>().null());
3611
3612
template <typename T>
3613
using boolean_function_t =
3614
    decltype(std::declval<T&>().boolean(std::declval<bool>()));
3615
3616
template <typename T, typename Integer>
3617
using number_integer_function_t =
3618
    decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
3619
3620
template <typename T, typename Unsigned>
3621
using number_unsigned_function_t =
3622
    decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
3623
3624
template <typename T, typename Float, typename String>
3625
using number_float_function_t = decltype(std::declval<T&>().number_float(
3626
                                    std::declval<Float>(), std::declval<const String&>()));
3627
3628
template <typename T, typename String>
3629
using string_function_t =
3630
    decltype(std::declval<T&>().string(std::declval<String&>()));
3631
3632
template <typename T>
3633
using start_object_function_t =
3634
    decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
3635
3636
template <typename T, typename String>
3637
using key_function_t =
3638
    decltype(std::declval<T&>().key(std::declval<String&>()));
3639
3640
template <typename T>
3641
using end_object_function_t = decltype(std::declval<T&>().end_object());
3642
3643
template <typename T>
3644
using start_array_function_t =
3645
    decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
3646
3647
template <typename T>
3648
using end_array_function_t = decltype(std::declval<T&>().end_array());
3649
3650
template <typename T, typename Exception>
3651
using parse_error_function_t = decltype(std::declval<T&>().parse_error(
3652
        std::declval<std::size_t>(), std::declval<const std::string&>(),
3653
        std::declval<const Exception&>()));
3654
3655
template <typename SAX, typename BasicJsonType>
3656
struct is_sax
3657
{
3658
  private:
3659
    static_assert(is_basic_json<BasicJsonType>::value,
3660
                  "BasicJsonType must be of type basic_json<...>");
3661
3662
    using number_integer_t = typename BasicJsonType::number_integer_t;
3663
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3664
    using number_float_t = typename BasicJsonType::number_float_t;
3665
    using string_t = typename BasicJsonType::string_t;
3666
    using exception_t = typename BasicJsonType::exception;
3667
3668
  public:
3669
    static constexpr bool value =
3670
        is_detected_exact<bool, null_function_t, SAX>::value &&
3671
        is_detected_exact<bool, boolean_function_t, SAX>::value &&
3672
        is_detected_exact<bool, number_integer_function_t, SAX,
3673
        number_integer_t>::value &&
3674
        is_detected_exact<bool, number_unsigned_function_t, SAX,
3675
        number_unsigned_t>::value &&
3676
        is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
3677
        string_t>::value &&
3678
        is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
3679
        is_detected_exact<bool, start_object_function_t, SAX>::value &&
3680
        is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
3681
        is_detected_exact<bool, end_object_function_t, SAX>::value &&
3682
        is_detected_exact<bool, start_array_function_t, SAX>::value &&
3683
        is_detected_exact<bool, end_array_function_t, SAX>::value &&
3684
        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
3685
};
3686
3687
template <typename SAX, typename BasicJsonType>
3688
struct is_sax_static_asserts
3689
{
3690
  private:
3691
    static_assert(is_basic_json<BasicJsonType>::value,
3692
                  "BasicJsonType must be of type basic_json<...>");
3693
3694
    using number_integer_t = typename BasicJsonType::number_integer_t;
3695
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3696
    using number_float_t = typename BasicJsonType::number_float_t;
3697
    using string_t = typename BasicJsonType::string_t;
3698
    using exception_t = typename BasicJsonType::exception;
3699
3700
  public:
3701
    static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
3702
                  "Missing/invalid function: bool null()");
3703
    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
3704
                  "Missing/invalid function: bool boolean(bool)");
3705
    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
3706
                  "Missing/invalid function: bool boolean(bool)");
3707
    static_assert(
3708
        is_detected_exact<bool, number_integer_function_t, SAX,
3709
        number_integer_t>::value,
3710
        "Missing/invalid function: bool number_integer(number_integer_t)");
3711
    static_assert(
3712
        is_detected_exact<bool, number_unsigned_function_t, SAX,
3713
        number_unsigned_t>::value,
3714
        "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
3715
    static_assert(is_detected_exact<bool, number_float_function_t, SAX,
3716
                  number_float_t, string_t>::value,
3717
                  "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
3718
    static_assert(
3719
        is_detected_exact<bool, string_function_t, SAX, string_t>::value,
3720
        "Missing/invalid function: bool string(string_t&)");
3721
    static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
3722
                  "Missing/invalid function: bool start_object(std::size_t)");
3723
    static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
3724
                  "Missing/invalid function: bool key(string_t&)");
3725
    static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
3726
                  "Missing/invalid function: bool end_object()");
3727
    static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
3728
                  "Missing/invalid function: bool start_array(std::size_t)");
3729
    static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
3730
                  "Missing/invalid function: bool end_array()");
3731
    static_assert(
3732
        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
3733
        "Missing/invalid function: bool parse_error(std::size_t, const "
3734
        "std::string&, const exception&)");
3735
};
3736
}
3737
}
3738
3739
// #include <nlohmann/detail/input/input_adapters.hpp>
3740
3741
// #include <nlohmann/detail/input/json_sax.hpp>
3742
3743
3744
#include <cstddef>
3745
#include <string>
3746
#include <vector>
3747
3748
// #include <nlohmann/detail/input/parser.hpp>
3749
3750
// #include <nlohmann/detail/exceptions.hpp>
3751
3752
3753
namespace nlohmann
3754
{
3755
3756
/*!
3757
@brief SAX interface
3758
3759
This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
3760
Each function is called in different situations while the input is parsed. The
3761
boolean return value informs the parser whether to continue processing the
3762
input.
3763
*/
3764
template<typename BasicJsonType>
3765
struct json_sax
3766
{
3767
    /// type for (signed) integers
3768
    using number_integer_t = typename BasicJsonType::number_integer_t;
3769
    /// type for unsigned integers
3770
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3771
    /// type for floating-point numbers
3772
    using number_float_t = typename BasicJsonType::number_float_t;
3773
    /// type for strings
3774
    using string_t = typename BasicJsonType::string_t;
3775
3776
    /*!
3777
    @brief a null value was read
3778
    @return whether parsing should proceed
3779
    */
3780
    virtual bool null() = 0;
3781
3782
    /*!
3783
    @brief a boolean value was read
3784
    @param[in] val  boolean value
3785
    @return whether parsing should proceed
3786
    */
3787
    virtual bool boolean(bool val) = 0;
3788
3789
    /*!
3790
    @brief an integer number was read
3791
    @param[in] val  integer value
3792
    @return whether parsing should proceed
3793
    */
3794
    virtual bool number_integer(number_integer_t val) = 0;
3795
3796
    /*!
3797
    @brief an unsigned integer number was read
3798
    @param[in] val  unsigned integer value
3799
    @return whether parsing should proceed
3800
    */
3801
    virtual bool number_unsigned(number_unsigned_t val) = 0;
3802
3803
    /*!
3804
    @brief an floating-point number was read
3805
    @param[in] val  floating-point value
3806
    @param[in] s    raw token value
3807
    @return whether parsing should proceed
3808
    */
3809
    virtual bool number_float(number_float_t val, const string_t& s) = 0;
3810
3811
    /*!
3812
    @brief a string was read
3813
    @param[in] val  string value
3814
    @return whether parsing should proceed
3815
    @note It is safe to move the passed string.
3816
    */
3817
    virtual bool string(string_t& val) = 0;
3818
3819
    /*!
3820
    @brief the beginning of an object was read
3821
    @param[in] elements  number of object elements or -1 if unknown
3822
    @return whether parsing should proceed
3823
    @note binary formats may report the number of elements
3824
    */
3825
    virtual bool start_object(std::size_t elements) = 0;
3826
3827
    /*!
3828
    @brief an object key was read
3829
    @param[in] val  object key
3830
    @return whether parsing should proceed
3831
    @note It is safe to move the passed string.
3832
    */
3833
    virtual bool key(string_t& val) = 0;
3834
3835
    /*!
3836
    @brief the end of an object was read
3837
    @return whether parsing should proceed
3838
    */
3839
    virtual bool end_object() = 0;
3840
3841
    /*!
3842
    @brief the beginning of an array was read
3843
    @param[in] elements  number of array elements or -1 if unknown
3844
    @return whether parsing should proceed
3845
    @note binary formats may report the number of elements
3846
    */
3847
    virtual bool start_array(std::size_t elements) = 0;
3848
3849
    /*!
3850
    @brief the end of an array was read
3851
    @return whether parsing should proceed
3852
    */
3853
    virtual bool end_array() = 0;
3854
3855
    /*!
3856
    @brief a parse error occurred
3857
    @param[in] position    the position in the input where the error occurs
3858
    @param[in] last_token  the last read token
3859
    @param[in] error_msg   a detailed error message
3860
    @return whether parsing should proceed (must return false)
3861
    */
3862
    virtual bool parse_error(std::size_t position,
3863
                             const std::string& last_token,
3864
                             const detail::exception& ex) = 0;
3865
3866
    virtual ~json_sax() = default;
3867
};
3868
3869
3870
namespace detail
3871
{
3872
/*!
3873
@brief SAX implementation to create a JSON value from SAX events
3874
3875
This class implements the @ref json_sax interface and processes the SAX events
3876
to create a JSON value which makes it basically a DOM parser. The structure or
3877
hierarchy of the JSON value is managed by the stack `ref_stack` which contains
3878
a pointer to the respective array or object for each recursion depth.
3879
3880
After successful parsing, the value that is passed by reference to the
3881
constructor contains the parsed value.
3882
3883
@tparam BasicJsonType  the JSON type
3884
*/
3885
template<typename BasicJsonType>
3886
class json_sax_dom_parser
3887
{
3888
  public:
3889
    using number_integer_t = typename BasicJsonType::number_integer_t;
3890
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3891
    using number_float_t = typename BasicJsonType::number_float_t;
3892
    using string_t = typename BasicJsonType::string_t;
3893
3894
    /*!
3895
    @param[in, out] r  reference to a JSON value that is manipulated while
3896
                       parsing
3897
    @param[in] allow_exceptions_  whether parse errors yield exceptions
3898
    */
3899
    explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
3900
        : root(r), allow_exceptions(allow_exceptions_)
2.34k
3901
    {}
3902
3903
    bool null()
1.11k
3904
    {
1.11k
3905
        handle_value(nullptr);
1.11k
3906
        return true;
1.11k
3907
    }
3908
3909
    bool boolean(bool val)
1.66k
3910
    {
1.66k
3911
        handle_value(val);
1.66k
3912
        return true;
1.66k
3913
    }
3914
3915
    bool number_integer(number_integer_t val)
25.3k
3916
    {
25.3k
3917
        handle_value(val);
25.3k
3918
        return true;
25.3k
3919
    }
3920
3921
    bool number_unsigned(number_unsigned_t val)
212k
3922
    {
212k
3923
        handle_value(val);
212k
3924
        return true;
212k
3925
    }
3926
3927
    bool number_float(number_float_t val, const string_t&)
158k
3928
    {
158k
3929
        handle_value(val);
158k
3930
        return true;
158k
3931
    }
3932
3933
    bool string(string_t& val)
169k
3934
    {
169k
3935
        handle_value(val);
169k
3936
        return true;
169k
3937
    }
3938
3939
    bool start_object(std::size_t len)
140k
3940
    {
140k
3941
        ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
140k
3942
140k
3943
        if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
0
3944
        {
0
3945
            JSON_THROW(out_of_range::create(408,
0
3946
                                            "excessive object size: " + std::to_string(len)));
0
3947
        }
140k
3948
140k
3949
        return true;
140k
3950
    }
3951
3952
    bool key(string_t& val)
681k
3953
    {
681k
3954
        // add null at given key and store the reference for later
681k
3955
        object_element = &(ref_stack.back()->m_value.object->operator[](val));
681k
3956
        return true;
681k
3957
    }
3958
3959
    bool end_object()
140k
3960
    {
140k
3961
        ref_stack.pop_back();
140k
3962
        return true;
140k
3963
    }
3964
3965
    bool start_array(std::size_t len)
1.66k
3966
    {
1.66k
3967
        ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
1.66k
3968
1.66k
3969
        if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
0
3970
        {
0
3971
            JSON_THROW(out_of_range::create(408,
0
3972
                                            "excessive array size: " + std::to_string(len)));
0
3973
        }
1.66k
3974
1.66k
3975
        return true;
1.66k
3976
    }
3977
3978
    bool end_array()
1.66k
3979
    {
1.66k
3980
        ref_stack.pop_back();
1.66k
3981
        return true;
1.66k
3982
    }
3983
3984
    bool parse_error(std::size_t, const std::string&,
3985
                     const detail::exception& ex)
0
3986
    {
0
3987
        errored = true;
0
3988
        if (allow_exceptions)
0
3989
        {
0
3990
            // determine the proper exception type from the id
0
3991
            switch ((ex.id / 100) % 100)
0
3992
            {
0
3993
                case 1:
0
3994
                    JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
0
3995
                case 4:
0
3996
                    JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
0
3997
                // LCOV_EXCL_START
0
3998
                case 2:
0
3999
                    JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
0
4000
                case 3:
0
4001
                    JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
0
4002
                case 5:
0
4003
                    JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
0
4004
                default:
0
4005
                    assert(false);
0
4006
                    // LCOV_EXCL_STOP
0
4007
            }
0
4008
        }
0
4009
        return false;
0
4010
    }
4011
4012
    constexpr bool is_errored() const
2.34k
4013
    {
2.34k
4014
        return errored;
2.34k
4015
    }
4016
4017
  private:
4018
    /*!
4019
    @invariant If the ref stack is empty, then the passed value will be the new
4020
               root.
4021
    @invariant If the ref stack contains a value, then it is an array or an
4022
               object to which we can add elements
4023
    */
4024
    template<typename Value>
4025
    BasicJsonType* handle_value(Value&& v)
710k
4026
    {
710k
4027
        if (ref_stack.empty())
2.34k
4028
        {
2.34k
4029
            root = BasicJsonType(std::forward<Value>(v));
2.34k
4030
            return &root;
2.34k
4031
        }
710k
4032
        else
708k
4033
        {
708k
4034
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
708k
4035
            if (ref_stack.back()->is_array())
26.4k
4036
            {
26.4k
4037
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
26.4k
4038
                return &(ref_stack.back()->m_value.array->back());
26.4k
4039
            }
708k
4040
            else
681k
4041
            {
681k
4042
                assert(object_element);
681k
4043
                *object_element = BasicJsonType(std::forward<Value>(v));
681k
4044
                return object_element;
681k
4045
            }
708k
4046
        }
710k
4047
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12handle_valueIRdEEPSC_OT_
158k
4026
    {
158k
4027
        if (ref_stack.empty())
0
4028
        {
0
4029
            root = BasicJsonType(std::forward<Value>(v));
0
4030
            return &root;
0
4031
        }
158k
4032
        else
158k
4033
        {
158k
4034
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
158k
4035
            if (ref_stack.back()->is_array())
0
4036
            {
0
4037
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
0
4038
                return &(ref_stack.back()->m_value.array->back());
0
4039
            }
158k
4040
            else
158k
4041
            {
158k
4042
                assert(object_element);
158k
4043
                *object_element = BasicJsonType(std::forward<Value>(v));
158k
4044
                return object_element;
158k
4045
            }
158k
4046
        }
158k
4047
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12handle_valueIRxEEPSC_OT_
25.3k
4026
    {
25.3k
4027
        if (ref_stack.empty())
0
4028
        {
0
4029
            root = BasicJsonType(std::forward<Value>(v));
0
4030
            return &root;
0
4031
        }
25.3k
4032
        else
25.3k
4033
        {
25.3k
4034
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
25.3k
4035
            if (ref_stack.back()->is_array())
0
4036
            {
0
4037
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
0
4038
                return &(ref_stack.back()->m_value.array->back());
0
4039
            }
25.3k
4040
            else
25.3k
4041
            {
25.3k
4042
                assert(object_element);
25.3k
4043
                *object_element = BasicJsonType(std::forward<Value>(v));
25.3k
4044
                return object_element;
25.3k
4045
            }
25.3k
4046
        }
25.3k
4047
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12handle_valueIRyEEPSC_OT_
212k
4026
    {
212k
4027
        if (ref_stack.empty())
0
4028
        {
0
4029
            root = BasicJsonType(std::forward<Value>(v));
0
4030
            return &root;
0
4031
        }
212k
4032
        else
212k
4033
        {
212k
4034
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
212k
4035
            if (ref_stack.back()->is_array())
0
4036
            {
0
4037
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
0
4038
                return &(ref_stack.back()->m_value.array->back());
0
4039
            }
212k
4040
            else
212k
4041
            {
212k
4042
                assert(object_element);
212k
4043
                *object_element = BasicJsonType(std::forward<Value>(v));
212k
4044
                return object_element;
212k
4045
            }
212k
4046
        }
212k
4047
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12handle_valueIRbEEPSC_OT_
1.66k
4026
    {
1.66k
4027
        if (ref_stack.empty())
0
4028
        {
0
4029
            root = BasicJsonType(std::forward<Value>(v));
0
4030
            return &root;
0
4031
        }
1.66k
4032
        else
1.66k
4033
        {
1.66k
4034
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
1.66k
4035
            if (ref_stack.back()->is_array())
0
4036
            {
0
4037
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
0
4038
                return &(ref_stack.back()->m_value.array->back());
0
4039
            }
1.66k
4040
            else
1.66k
4041
            {
1.66k
4042
                assert(object_element);
1.66k
4043
                *object_element = BasicJsonType(std::forward<Value>(v));
1.66k
4044
                return object_element;
1.66k
4045
            }
1.66k
4046
        }
1.66k
4047
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12handle_valueINS0_7value_tEEEPSC_OT_
141k
4026
    {
141k
4027
        if (ref_stack.empty())
2.34k
4028
        {
2.34k
4029
            root = BasicJsonType(std::forward<Value>(v));
2.34k
4030
            return &root;
2.34k
4031
        }
141k
4032
        else
139k
4033
        {
139k
4034
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
139k
4035
            if (ref_stack.back()->is_array())
26.4k
4036
            {
26.4k
4037
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
26.4k
4038
                return &(ref_stack.back()->m_value.array->back());
26.4k
4039
            }
139k
4040
            else
113k
4041
            {
113k
4042
                assert(object_element);
113k
4043
                *object_element = BasicJsonType(std::forward<Value>(v));
113k
4044
                return object_element;
113k
4045
            }
139k
4046
        }
141k
4047
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12handle_valueIRSA_EEPSC_OT_
169k
4026
    {
169k
4027
        if (ref_stack.empty())
0
4028
        {
0
4029
            root = BasicJsonType(std::forward<Value>(v));
0
4030
            return &root;
0
4031
        }
169k
4032
        else
169k
4033
        {
169k
4034
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
169k
4035
            if (ref_stack.back()->is_array())
0
4036
            {
0
4037
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
0
4038
                return &(ref_stack.back()->m_value.array->back());
0
4039
            }
169k
4040
            else
169k
4041
            {
169k
4042
                assert(object_element);
169k
4043
                *object_element = BasicJsonType(std::forward<Value>(v));
169k
4044
                return object_element;
169k
4045
            }
169k
4046
        }
169k
4047
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12handle_valueIDnEEPSC_OT_
1.11k
4026
    {
1.11k
4027
        if (ref_stack.empty())
0
4028
        {
0
4029
            root = BasicJsonType(std::forward<Value>(v));
0
4030
            return &root;
0
4031
        }
1.11k
4032
        else
1.11k
4033
        {
1.11k
4034
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
1.11k
4035
            if (ref_stack.back()->is_array())
0
4036
            {
0
4037
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
0
4038
                return &(ref_stack.back()->m_value.array->back());
0
4039
            }
1.11k
4040
            else
1.11k
4041
            {
1.11k
4042
                assert(object_element);
1.11k
4043
                *object_element = BasicJsonType(std::forward<Value>(v));
1.11k
4044
                return object_element;
1.11k
4045
            }
1.11k
4046
        }
1.11k
4047
    }
4048
4049
    /// the parsed JSON value
4050
    BasicJsonType& root;
4051
    /// stack to model hierarchy of values
4052
    std::vector<BasicJsonType*> ref_stack;
4053
    /// helper to hold the reference for the next object element
4054
    BasicJsonType* object_element = nullptr;
4055
    /// whether a syntax error occurred
4056
    bool errored = false;
4057
    /// whether to throw exceptions in case of errors
4058
    const bool allow_exceptions = true;
4059
};
4060
4061
template<typename BasicJsonType>
4062
class json_sax_dom_callback_parser
4063
{
4064
  public:
4065
    using number_integer_t = typename BasicJsonType::number_integer_t;
4066
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4067
    using number_float_t = typename BasicJsonType::number_float_t;
4068
    using string_t = typename BasicJsonType::string_t;
4069
    using parser_callback_t = typename BasicJsonType::parser_callback_t;
4070
    using parse_event_t = typename BasicJsonType::parse_event_t;
4071
4072
    json_sax_dom_callback_parser(BasicJsonType& r,
4073
                                 const parser_callback_t cb,
4074
                                 const bool allow_exceptions_ = true)
4075
        : root(r), callback(cb), allow_exceptions(allow_exceptions_)
0
4076
    {
0
4077
        keep_stack.push_back(true);
0
4078
    }
4079
4080
    bool null()
0
4081
    {
0
4082
        handle_value(nullptr);
0
4083
        return true;
0
4084
    }
4085
4086
    bool boolean(bool val)
0
4087
    {
0
4088
        handle_value(val);
0
4089
        return true;
0
4090
    }
4091
4092
    bool number_integer(number_integer_t val)
0
4093
    {
0
4094
        handle_value(val);
0
4095
        return true;
0
4096
    }
4097
4098
    bool number_unsigned(number_unsigned_t val)
0
4099
    {
0
4100
        handle_value(val);
0
4101
        return true;
0
4102
    }
4103
4104
    bool number_float(number_float_t val, const string_t&)
0
4105
    {
0
4106
        handle_value(val);
0
4107
        return true;
0
4108
    }
4109
4110
    bool string(string_t& val)
0
4111
    {
0
4112
        handle_value(val);
0
4113
        return true;
0
4114
    }
4115
4116
    bool start_object(std::size_t len)
0
4117
    {
0
4118
        // check callback for object start
0
4119
        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
0
4120
        keep_stack.push_back(keep);
0
4121
0
4122
        auto val = handle_value(BasicJsonType::value_t::object, true);
0
4123
        ref_stack.push_back(val.second);
0
4124
0
4125
        // check object limit
0
4126
        if (ref_stack.back())
0
4127
        {
0
4128
            if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
0
4129
            {
0
4130
                JSON_THROW(out_of_range::create(408,
0
4131
                                                "excessive object size: " + std::to_string(len)));
0
4132
            }
0
4133
        }
0
4134
0
4135
        return true;
0
4136
    }
4137
4138
    bool key(string_t& val)
0
4139
    {
0
4140
        BasicJsonType k = BasicJsonType(val);
0
4141
0
4142
        // check callback for key
0
4143
        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
0
4144
        key_keep_stack.push_back(keep);
0
4145
0
4146
        // add discarded value at given key and store the reference for later
0
4147
        if (keep and ref_stack.back())
0
4148
        {
0
4149
            object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
0
4150
        }
0
4151
0
4152
        return true;
0
4153
    }
4154
4155
    bool end_object()
0
4156
    {
0
4157
        if (ref_stack.back())
0
4158
        {
0
4159
            if (not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
0
4160
            {
0
4161
                // discard object
0
4162
                *ref_stack.back() = discarded;
0
4163
            }
0
4164
        }
0
4165
0
4166
        assert(not ref_stack.empty());
0
4167
        assert(not keep_stack.empty());
0
4168
        ref_stack.pop_back();
0
4169
        keep_stack.pop_back();
0
4170
0
4171
        if (not ref_stack.empty() and ref_stack.back())
0
4172
        {
0
4173
            // remove discarded value
0
4174
            if (ref_stack.back()->is_object())
0
4175
            {
0
4176
                for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
0
4177
                {
0
4178
                    if (it->is_discarded())
0
4179
                    {
0
4180
                        ref_stack.back()->erase(it);
0
4181
                        break;
0
4182
                    }
0
4183
                }
0
4184
            }
0
4185
        }
0
4186
0
4187
        return true;
0
4188
    }
4189
4190
    bool start_array(std::size_t len)
0
4191
    {
0
4192
        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
0
4193
        keep_stack.push_back(keep);
0
4194
0
4195
        auto val = handle_value(BasicJsonType::value_t::array, true);
0
4196
        ref_stack.push_back(val.second);
0
4197
0
4198
        // check array limit
0
4199
        if (ref_stack.back())
0
4200
        {
0
4201
            if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
0
4202
            {
0
4203
                JSON_THROW(out_of_range::create(408,
0
4204
                                                "excessive array size: " + std::to_string(len)));
0
4205
            }
0
4206
        }
0
4207
0
4208
        return true;
0
4209
    }
4210
4211
    bool end_array()
0
4212
    {
0
4213
        bool keep = true;
0
4214
0
4215
        if (ref_stack.back())
0
4216
        {
0
4217
            keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
0
4218
            if (not keep)
0
4219
            {
0
4220
                // discard array
0
4221
                *ref_stack.back() = discarded;
0
4222
            }
0
4223
        }
0
4224
0
4225
        assert(not ref_stack.empty());
0
4226
        assert(not keep_stack.empty());
0
4227
        ref_stack.pop_back();
0
4228
        keep_stack.pop_back();
0
4229
0
4230
        // remove discarded value
0
4231
        if (not keep and not ref_stack.empty())
0
4232
        {
0
4233
            if (ref_stack.back()->is_array())
0
4234
            {
0
4235
                ref_stack.back()->m_value.array->pop_back();
0
4236
            }
0
4237
        }
0
4238
0
4239
        return true;
0
4240
    }
4241
4242
    bool parse_error(std::size_t, const std::string&,
4243
                     const detail::exception& ex)
0
4244
    {
0
4245
        errored = true;
0
4246
        if (allow_exceptions)
0
4247
        {
0
4248
            // determine the proper exception type from the id
0
4249
            switch ((ex.id / 100) % 100)
0
4250
            {
0
4251
                case 1:
0
4252
                    JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
0
4253
                case 4:
0
4254
                    JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
0
4255
                // LCOV_EXCL_START
0
4256
                case 2:
0
4257
                    JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
0
4258
                case 3:
0
4259
                    JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
0
4260
                case 5:
0
4261
                    JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
0
4262
                default:
0
4263
                    assert(false);
0
4264
                    // LCOV_EXCL_STOP
0
4265
            }
0
4266
        }
0
4267
        return false;
0
4268
    }
4269
4270
    constexpr bool is_errored() const
0
4271
    {
0
4272
        return errored;
0
4273
    }
4274
4275
  private:
4276
    /*!
4277
    @param[in] v  value to add to the JSON value we build during parsing
4278
    @param[in] skip_callback  whether we should skip calling the callback
4279
               function; this is required after start_array() and
4280
               start_object() SAX events, because otherwise we would call the
4281
               callback function with an empty array or object, respectively.
4282
4283
    @invariant If the ref stack is empty, then the passed value will be the new
4284
               root.
4285
    @invariant If the ref stack contains a value, then it is an array or an
4286
               object to which we can add elements
4287
4288
    @return pair of boolean (whether value should be kept) and pointer (to the
4289
            passed value in the ref_stack hierarchy; nullptr if not kept)
4290
    */
4291
    template<typename Value>
4292
    std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
0
4293
    {
0
4294
        assert(not keep_stack.empty());
0
4295
0
4296
        // do not handle this value if we know it would be added to a discarded
0
4297
        // container
0
4298
        if (not keep_stack.back())
0
4299
        {
0
4300
            return {false, nullptr};
0
4301
        }
0
4302
0
4303
        // create value
0
4304
        auto value = BasicJsonType(std::forward<Value>(v));
0
4305
0
4306
        // check callback
0
4307
        const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
0
4308
0
4309
        // do not handle this value if we just learnt it shall be discarded
0
4310
        if (not keep)
0
4311
        {
0
4312
            return {false, nullptr};
0
4313
        }
0
4314
0
4315
        if (ref_stack.empty())
0
4316
        {
0
4317
            root = std::move(value);
0
4318
            return {true, &root};
0
4319
        }
0
4320
        else
0
4321
        {
0
4322
            // skip this value if we already decided to skip the parent
0
4323
            // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
0
4324
            if (not ref_stack.back())
0
4325
            {
0
4326
                return {false, nullptr};
0
4327
            }
0
4328
0
4329
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
0
4330
            if (ref_stack.back()->is_array())
0
4331
            {
0
4332
                ref_stack.back()->m_value.array->push_back(std::move(value));
0
4333
                return {true, &(ref_stack.back()->m_value.array->back())};
0
4334
            }
0
4335
            else
0
4336
            {
0
4337
                // check if we should store an element for the current key
0
4338
                assert(not key_keep_stack.empty());
0
4339
                const bool store_element = key_keep_stack.back();
0
4340
                key_keep_stack.pop_back();
0
4341
0
4342
                if (not store_element)
0
4343
                {
0
4344
                    return {false, nullptr};
0
4345
                }
0
4346
0
4347
                assert(object_element);
0
4348
                *object_element = std::move(value);
0
4349
                return {true, object_element};
0
4350
            }
0
4351
        }
0
4352
    }
_ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12handle_valueIRxEESt4pairIbPSC_EOT_b
0
4293
    {
0
4294
        assert(not keep_stack.empty());
0
4295
0
4296
        // do not handle this value if we know it would be added to a discarded
0
4297
        // container
0
4298
        if (not keep_stack.back())
0
4299
        {
0
4300
            return {false, nullptr};
0
4301
        }
0
4302
0
4303
        // create value
0
4304
        auto value = BasicJsonType(std::forward<Value>(v));
0
4305
0
4306
        // check callback
0
4307
        const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
0
4308
0
4309
        // do not handle this value if we just learnt it shall be discarded
0
4310
        if (not keep)
0
4311
        {
0
4312
            return {false, nullptr};
0
4313
        }
0
4314
0
4315
        if (ref_stack.empty())
0
4316
        {
0
4317
            root = std::move(value);
0
4318
            return {true, &root};
0
4319
        }
0
4320
        else
0
4321
        {
0
4322
            // skip this value if we already decided to skip the parent
0
4323
            // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
0
4324
            if (not ref_stack.back())
0
4325
            {
0
4326
                return {false, nullptr};
0
4327
            }
0
4328
0
4329
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
0
4330
            if (ref_stack.back()->is_array())
0
4331
            {
0
4332
                ref_stack.back()->m_value.array->push_back(std::move(value));
0
4333
                return {true, &(ref_stack.back()->m_value.array->back())};
0
4334
            }
0
4335
            else
0
4336
            {
0
4337
                // check if we should store an element for the current key
0
4338
                assert(not key_keep_stack.empty());
0
4339
                const bool store_element = key_keep_stack.back();
0
4340
                key_keep_stack.pop_back();
0
4341
0
4342
                if (not store_element)
0
4343
                {
0
4344
                    return {false, nullptr};
0
4345
                }
0
4346
0
4347
                assert(object_element);
0
4348
                *object_element = std::move(value);
0
4349
                return {true, object_element};
0
4350
            }
0
4351
        }
0
4352
    }
_ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12handle_valueIRSA_EESt4pairIbPSC_EOT_b
0
4293
    {
0
4294
        assert(not keep_stack.empty());
0
4295
0
4296
        // do not handle this value if we know it would be added to a discarded
0
4297
        // container
0
4298
        if (not keep_stack.back())
0
4299
        {
0
4300
            return {false, nullptr};
0
4301
        }
0
4302
0
4303
        // create value
0
4304
        auto value = BasicJsonType(std::forward<Value>(v));
0
4305
0
4306
        // check callback
0
4307
        const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
0
4308
0
4309
        // do not handle this value if we just learnt it shall be discarded
0
4310
        if (not keep)
0
4311
        {
0
4312
            return {false, nullptr};
0
4313
        }
0
4314
0
4315
        if (ref_stack.empty())
0
4316
        {
0
4317
            root = std::move(value);
0
4318
            return {true, &root};
0
4319
        }
0
4320
        else
0
4321
        {
0
4322
            // skip this value if we already decided to skip the parent
0
4323
            // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
0
4324
            if (not ref_stack.back())
0
4325
            {
0
4326
                return {false, nullptr};
0
4327
            }
0
4328
0
4329
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
0
4330
            if (ref_stack.back()->is_array())
0
4331
            {
0
4332
                ref_stack.back()->m_value.array->push_back(std::move(value));
0
4333
                return {true, &(ref_stack.back()->m_value.array->back())};
0
4334
            }
0
4335
            else
0
4336
            {
0
4337
                // check if we should store an element for the current key
0
4338
                assert(not key_keep_stack.empty());
0
4339
                const bool store_element = key_keep_stack.back();
0
4340
                key_keep_stack.pop_back();
0
4341
0
4342
                if (not store_element)
0
4343
                {
0
4344
                    return {false, nullptr};
0
4345
                }
0
4346
0
4347
                assert(object_element);
0
4348
                *object_element = std::move(value);
0
4349
                return {true, object_element};
0
4350
            }
0
4351
        }
0
4352
    }
_ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12handle_valueIRyEESt4pairIbPSC_EOT_b
0
4293
    {
0
4294
        assert(not keep_stack.empty());
0
4295
0
4296
        // do not handle this value if we know it would be added to a discarded
0
4297
        // container
0
4298
        if (not keep_stack.back())
0
4299
        {
0
4300
            return {false, nullptr};
0
4301
        }
0
4302
0
4303
        // create value
0
4304
        auto value = BasicJsonType(std::forward<Value>(v));
0
4305
0
4306
        // check callback
0
4307
        const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
0
4308
0
4309
        // do not handle this value if we just learnt it shall be discarded
0
4310
        if (not keep)
0
4311
        {
0
4312
            return {false, nullptr};
0
4313
        }
0
4314
0
4315
        if (ref_stack.empty())
0
4316
        {
0
4317
            root = std::move(value);
0
4318
            return {true, &root};
0
4319
        }
0
4320
        else
0
4321
        {
0
4322
            // skip this value if we already decided to skip the parent
0
4323
            // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
0
4324
            if (not ref_stack.back())
0
4325
            {
0
4326
                return {false, nullptr};
0
4327
            }
0
4328
0
4329
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
0
4330
            if (ref_stack.back()->is_array())
0
4331
            {
0
4332
                ref_stack.back()->m_value.array->push_back(std::move(value));
0
4333
                return {true, &(ref_stack.back()->m_value.array->back())};
0
4334
            }
0
4335
            else
0
4336
            {
0
4337
                // check if we should store an element for the current key
0
4338
                assert(not key_keep_stack.empty());
0
4339
                const bool store_element = key_keep_stack.back();
0
4340
                key_keep_stack.pop_back();
0
4341
0
4342
                if (not store_element)
0
4343
                {
0
4344
                    return {false, nullptr};
0
4345
                }
0
4346
0
4347
                assert(object_element);
0
4348
                *object_element = std::move(value);
0
4349
                return {true, object_element};
0
4350
            }
0
4351
        }
0
4352
    }
_ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12handle_valueIRbEESt4pairIbPSC_EOT_b
0
4293
    {
0
4294
        assert(not keep_stack.empty());
0
4295
0
4296
        // do not handle this value if we know it would be added to a discarded
0
4297
        // container
0
4298
        if (not keep_stack.back())
0
4299
        {
0
4300
            return {false, nullptr};
0
4301
        }
0
4302
0
4303
        // create value
0
4304
        auto value = BasicJsonType(std::forward<Value>(v));
0
4305
0
4306
        // check callback
0
4307
        const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
0
4308
0
4309
        // do not handle this value if we just learnt it shall be discarded
0
4310
        if (not keep)
0
4311
        {
0
4312
            return {false, nullptr};
0
4313
        }
0
4314
0
4315
        if (ref_stack.empty())
0
4316
        {
0
4317
            root = std::move(value);
0
4318
            return {true, &root};
0
4319
        }
0
4320
        else
0
4321
        {
0
4322
            // skip this value if we already decided to skip the parent
0
4323
            // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
0
4324
            if (not ref_stack.back())
0
4325
            {
0
4326
                return {false, nullptr};
0
4327
            }
0
4328
0
4329
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
0
4330
            if (ref_stack.back()->is_array())
0
4331
            {
0
4332
                ref_stack.back()->m_value.array->push_back(std::move(value));
0
4333
                return {true, &(ref_stack.back()->m_value.array->back())};
0
4334
            }
0
4335
            else
0
4336
            {
0
4337
                // check if we should store an element for the current key
0
4338
                assert(not key_keep_stack.empty());
0
4339
                const bool store_element = key_keep_stack.back();
0
4340
                key_keep_stack.pop_back();
0
4341
0
4342
                if (not store_element)
0
4343
                {
0
4344
                    return {false, nullptr};
0
4345
                }
0
4346
0
4347
                assert(object_element);
0
4348
                *object_element = std::move(value);
0
4349
                return {true, object_element};
0
4350
            }
0
4351
        }
0
4352
    }
_ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12handle_valueIRdEESt4pairIbPSC_EOT_b
0
4293
    {
0
4294
        assert(not keep_stack.empty());
0
4295
0
4296
        // do not handle this value if we know it would be added to a discarded
0
4297
        // container
0
4298
        if (not keep_stack.back())
0
4299
        {
0
4300
            return {false, nullptr};
0
4301
        }
0
4302
0
4303
        // create value
0
4304
        auto value = BasicJsonType(std::forward<Value>(v));
0
4305
0
4306
        // check callback
0
4307
        const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
0
4308
0
4309
        // do not handle this value if we just learnt it shall be discarded
0
4310
        if (not keep)
0
4311
        {
0
4312
            return {false, nullptr};
0
4313
        }
0
4314
0
4315
        if (ref_stack.empty())
0
4316
        {
0
4317
            root = std::move(value);
0
4318
            return {true, &root};
0
4319
        }
0
4320
        else
0
4321
        {
0
4322
            // skip this value if we already decided to skip the parent
0
4323
            // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
0
4324
            if (not ref_stack.back())
0
4325
            {
0
4326
                return {false, nullptr};
0
4327
            }
0
4328
0
4329
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
0
4330
            if (ref_stack.back()->is_array())
0
4331
            {
0
4332
                ref_stack.back()->m_value.array->push_back(std::move(value));
0
4333
                return {true, &(ref_stack.back()->m_value.array->back())};
0
4334
            }
0
4335
            else
0
4336
            {
0
4337
                // check if we should store an element for the current key
0
4338
                assert(not key_keep_stack.empty());
0
4339
                const bool store_element = key_keep_stack.back();
0
4340
                key_keep_stack.pop_back();
0
4341
0
4342
                if (not store_element)
0
4343
                {
0
4344
                    return {false, nullptr};
0
4345
                }
0
4346
0
4347
                assert(object_element);
0
4348
                *object_element = std::move(value);
0
4349
                return {true, object_element};
0
4350
            }
0
4351
        }
0
4352
    }
_ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12handle_valueINS0_7value_tEEESt4pairIbPSC_EOT_b
0
4293
    {
0
4294
        assert(not keep_stack.empty());
0
4295
0
4296
        // do not handle this value if we know it would be added to a discarded
0
4297
        // container
0
4298
        if (not keep_stack.back())
0
4299
        {
0
4300
            return {false, nullptr};
0
4301
        }
0
4302
0
4303
        // create value
0
4304
        auto value = BasicJsonType(std::forward<Value>(v));
0
4305
0
4306
        // check callback
0
4307
        const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
0
4308
0
4309
        // do not handle this value if we just learnt it shall be discarded
0
4310
        if (not keep)
0
4311
        {
0
4312
            return {false, nullptr};
0
4313
        }
0
4314
0
4315
        if (ref_stack.empty())
0
4316
        {
0
4317
            root = std::move(value);
0
4318
            return {true, &root};
0
4319
        }
0
4320
        else
0
4321
        {
0
4322
            // skip this value if we already decided to skip the parent
0
4323
            // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
0
4324
            if (not ref_stack.back())
0
4325
            {
0
4326
                return {false, nullptr};
0
4327
            }
0
4328
0
4329
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
0
4330
            if (ref_stack.back()->is_array())
0
4331
            {
0
4332
                ref_stack.back()->m_value.array->push_back(std::move(value));
0
4333
                return {true, &(ref_stack.back()->m_value.array->back())};
0
4334
            }
0
4335
            else
0
4336
            {
0
4337
                // check if we should store an element for the current key
0
4338
                assert(not key_keep_stack.empty());
0
4339
                const bool store_element = key_keep_stack.back();
0
4340
                key_keep_stack.pop_back();
0
4341
0
4342
                if (not store_element)
0
4343
                {
0
4344
                    return {false, nullptr};
0
4345
                }
0
4346
0
4347
                assert(object_element);
0
4348
                *object_element = std::move(value);
0
4349
                return {true, object_element};
0
4350
            }
0
4351
        }
0
4352
    }
_ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12handle_valueIDnEESt4pairIbPSC_EOT_b
0
4293
    {
0
4294
        assert(not keep_stack.empty());
0
4295
0
4296
        // do not handle this value if we know it would be added to a discarded
0
4297
        // container
0
4298
        if (not keep_stack.back())
0
4299
        {
0
4300
            return {false, nullptr};
0
4301
        }
0
4302
0
4303
        // create value
0
4304
        auto value = BasicJsonType(std::forward<Value>(v));
0
4305
0
4306
        // check callback
0
4307
        const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
0
4308
0
4309
        // do not handle this value if we just learnt it shall be discarded
0
4310
        if (not keep)
0
4311
        {
0
4312
            return {false, nullptr};
0
4313
        }
0
4314
0
4315
        if (ref_stack.empty())
0
4316
        {
0
4317
            root = std::move(value);
0
4318
            return {true, &root};
0
4319
        }
0
4320
        else
0
4321
        {
0
4322
            // skip this value if we already decided to skip the parent
0
4323
            // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
0
4324
            if (not ref_stack.back())
0
4325
            {
0
4326
                return {false, nullptr};
0
4327
            }
0
4328
0
4329
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
0
4330
            if (ref_stack.back()->is_array())
0
4331
            {
0
4332
                ref_stack.back()->m_value.array->push_back(std::move(value));
0
4333
                return {true, &(ref_stack.back()->m_value.array->back())};
0
4334
            }
0
4335
            else
0
4336
            {
0
4337
                // check if we should store an element for the current key
0
4338
                assert(not key_keep_stack.empty());
0
4339
                const bool store_element = key_keep_stack.back();
0
4340
                key_keep_stack.pop_back();
0
4341
0
4342
                if (not store_element)
0
4343
                {
0
4344
                    return {false, nullptr};
0
4345
                }
0
4346
0
4347
                assert(object_element);
0
4348
                *object_element = std::move(value);
0
4349
                return {true, object_element};
0
4350
            }
0
4351
        }
0
4352
    }
4353
4354
    /// the parsed JSON value
4355
    BasicJsonType& root;
4356
    /// stack to model hierarchy of values
4357
    std::vector<BasicJsonType*> ref_stack;
4358
    /// stack to manage which values to keep
4359
    std::vector<bool> keep_stack;
4360
    /// stack to manage which object keys to keep
4361
    std::vector<bool> key_keep_stack;
4362
    /// helper to hold the reference for the next object element
4363
    BasicJsonType* object_element = nullptr;
4364
    /// whether a syntax error occurred
4365
    bool errored = false;
4366
    /// callback function
4367
    const parser_callback_t callback = nullptr;
4368
    /// whether to throw exceptions in case of errors
4369
    const bool allow_exceptions = true;
4370
    /// a discarded value for the callback
4371
    BasicJsonType discarded = BasicJsonType::value_t::discarded;
4372
};
4373
4374
template<typename BasicJsonType>
4375
class json_sax_acceptor
4376
{
4377
  public:
4378
    using number_integer_t = typename BasicJsonType::number_integer_t;
4379
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4380
    using number_float_t = typename BasicJsonType::number_float_t;
4381
    using string_t = typename BasicJsonType::string_t;
4382
4383
    bool null()
4384
    {
4385
        return true;
4386
    }
4387
4388
    bool boolean(bool)
4389
    {
4390
        return true;
4391
    }
4392
4393
    bool number_integer(number_integer_t)
4394
    {
4395
        return true;
4396
    }
4397
4398
    bool number_unsigned(number_unsigned_t)
4399
    {
4400
        return true;
4401
    }
4402
4403
    bool number_float(number_float_t, const string_t&)
4404
    {
4405
        return true;
4406
    }
4407
4408
    bool string(string_t&)
4409
    {
4410
        return true;
4411
    }
4412
4413
    bool start_object(std::size_t = std::size_t(-1))
4414
    {
4415
        return true;
4416
    }
4417
4418
    bool key(string_t&)
4419
    {
4420
        return true;
4421
    }
4422
4423
    bool end_object()
4424
    {
4425
        return true;
4426
    }
4427
4428
    bool start_array(std::size_t = std::size_t(-1))
4429
    {
4430
        return true;
4431
    }
4432
4433
    bool end_array()
4434
    {
4435
        return true;
4436
    }
4437
4438
    bool parse_error(std::size_t, const std::string&, const detail::exception&)
4439
    {
4440
        return false;
4441
    }
4442
};
4443
}
4444
4445
}
4446
4447
// #include <nlohmann/detail/input/lexer.hpp>
4448
4449
// #include <nlohmann/detail/value_t.hpp>
4450
4451
4452
namespace nlohmann
4453
{
4454
namespace detail
4455
{
4456
////////////
4457
// parser //
4458
////////////
4459
4460
/*!
4461
@brief syntax analysis
4462
4463
This class implements a recursive decent parser.
4464
*/
4465
template<typename BasicJsonType>
4466
class parser
4467
{
4468
    using number_integer_t = typename BasicJsonType::number_integer_t;
4469
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4470
    using number_float_t = typename BasicJsonType::number_float_t;
4471
    using string_t = typename BasicJsonType::string_t;
4472
    using lexer_t = lexer<BasicJsonType>;
4473
    using token_type = typename lexer_t::token_type;
4474
4475
  public:
4476
    enum class parse_event_t : uint8_t
4477
    {
4478
        /// the parser read `{` and started to process a JSON object
4479
        object_start,
4480
        /// the parser read `}` and finished processing a JSON object
4481
        object_end,
4482
        /// the parser read `[` and started to process a JSON array
4483
        array_start,
4484
        /// the parser read `]` and finished processing a JSON array
4485
        array_end,
4486
        /// the parser read a key of a value in an object
4487
        key,
4488
        /// the parser finished reading a JSON value
4489
        value
4490
    };
4491
4492
    using parser_callback_t =
4493
        std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
4494
4495
    /// a parser reading from an input adapter
4496
    explicit parser(detail::input_adapter_t&& adapter,
4497
                    const parser_callback_t cb = nullptr,
4498
                    const bool allow_exceptions_ = true)
4499
        : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
2.34k
4500
    {
2.34k
4501
        // read first token
2.34k
4502
        get_token();
2.34k
4503
    }
4504
4505
    /*!
4506
    @brief public parser interface
4507
4508
    @param[in] strict      whether to expect the last token to be EOF
4509
    @param[in,out] result  parsed JSON value
4510
4511
    @throw parse_error.101 in case of an unexpected token
4512
    @throw parse_error.102 if to_unicode fails or surrogate error
4513
    @throw parse_error.103 if to_unicode fails
4514
    */
4515
    void parse(const bool strict, BasicJsonType& result)
2.34k
4516
    {
2.34k
4517
        if (callback)
0
4518
        {
0
4519
            json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
0
4520
            sax_parse_internal(&sdp);
0
4521
            result.assert_invariant();
0
4522
0
4523
            // in strict mode, input must be completely read
0
4524
            if (strict and (get_token() != token_type::end_of_input))
0
4525
            {
0
4526
                sdp.parse_error(m_lexer.get_position(),
0
4527
                                m_lexer.get_token_string(),
0
4528
                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
0
4529
            }
0
4530
0
4531
            // in case of an error, return discarded value
0
4532
            if (sdp.is_errored())
0
4533
            {
0
4534
                result = value_t::discarded;
0
4535
                return;
0
4536
            }
0
4537
0
4538
            // set top-level value to null if it was discarded by the callback
0
4539
            // function
0
4540
            if (result.is_discarded())
0
4541
            {
0
4542
                result = nullptr;
0
4543
            }
0
4544
        }
2.34k
4545
        else
2.34k
4546
        {
2.34k
4547
            json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
2.34k
4548
            sax_parse_internal(&sdp);
2.34k
4549
            result.assert_invariant();
2.34k
4550
2.34k
4551
            // in strict mode, input must be completely read
2.34k
4552
            if (strict and (get_token() != token_type::end_of_input))
0
4553
            {
0
4554
                sdp.parse_error(m_lexer.get_position(),
0
4555
                                m_lexer.get_token_string(),
0
4556
                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
0
4557
            }
2.34k
4558
2.34k
4559
            // in case of an error, return discarded value
2.34k
4560
            if (sdp.is_errored())
0
4561
            {
0
4562
                result = value_t::discarded;
0
4563
                return;
0
4564
            }
2.34k
4565
        }
2.34k
4566
    }
4567
4568
    /*!
4569
    @brief public accept interface
4570
4571
    @param[in] strict  whether to expect the last token to be EOF
4572
    @return whether the input is a proper JSON text
4573
    */
4574
    bool accept(const bool strict = true)
4575
    {
4576
        json_sax_acceptor<BasicJsonType> sax_acceptor;
4577
        return sax_parse(&sax_acceptor, strict);
4578
    }
4579
4580
    template <typename SAX>
4581
    bool sax_parse(SAX* sax, const bool strict = true)
4582
    {
4583
        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
4584
        const bool result = sax_parse_internal(sax);
4585
4586
        // strict mode: next byte must be EOF
4587
        if (result and strict and (get_token() != token_type::end_of_input))
4588
        {
4589
            return sax->parse_error(m_lexer.get_position(),
4590
                                    m_lexer.get_token_string(),
4591
                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
4592
        }
4593
4594
        return result;
4595
    }
4596
4597
  private:
4598
    template <typename SAX>
4599
    bool sax_parse_internal(SAX* sax)
2.34k
4600
    {
2.34k
4601
        // stack to remember the hieararchy of structured values we are parsing
2.34k
4602
        // true = array; false = object
2.34k
4603
        std::vector<bool> states;
2.34k
4604
        // value to avoid a goto (see comment where set to true)
2.34k
4605
        bool skip_to_state_evaluation = false;
2.34k
4606
851k
4607
        while (true)
851k
4608
        {
851k
4609
            if (not skip_to_state_evaluation)
710k
4610
            {
710k
4611
                // invariant: get_token() was called before each iteration
569k
4612
                switch (last_token)
569k
4613
                {
140k
4614
                    case token_type::begin_object:
140k
4615
                    {
140k
4616
                        if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
0
4617
                        {
0
4618
                            return false;
0
4619
                        }
140k
4620
140k
4621
                        // closing } -> we are done
140k
4622
                        if (get_token() == token_type::end_object)
0
4623
                        {
0
4624
                            if (JSON_UNLIKELY(not sax->end_object()))
0
4625
                            {
0
4626
                                return false;
0
4627
                            }
0
4628
                            break;
0
4629
                        }
140k
4630
140k
4631
                        // parse key
140k
4632
                        if (JSON_UNLIKELY(last_token != token_type::value_string))
0
4633
                        {
0
4634
                            return sax->parse_error(m_lexer.get_position(),
0
4635
                                                    m_lexer.get_token_string(),
0
4636
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
0
4637
                        }
140k
4638
                        else
140k
4639
                        {
140k
4640
                            if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
0
4641
                            {
0
4642
                                return false;
0
4643
                            }
140k
4644
                        }
140k
4645
140k
4646
                        // parse separator (:)
140k
4647
                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))
0
4648
                        {
0
4649
                            return sax->parse_error(m_lexer.get_position(),
0
4650
                                                    m_lexer.get_token_string(),
0
4651
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
0
4652
                        }
140k
4653
140k
4654
                        // remember we are now inside an object
140k
4655
                        states.push_back(false);
140k
4656
140k
4657
                        // parse values
140k
4658
                        get_token();
140k
4659
                        continue;
140k
4660
                    }
140k
4661
1.66k
4662
                    case token_type::begin_array:
1.66k
4663
                    {
1.66k
4664
                        if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
0
4665
                        {
0
4666
                            return false;
0
4667
                        }
1.66k
4668
1.66k
4669
                        // closing ] -> we are done
1.66k
4670
                        if (get_token() == token_type::end_array)
548
4671
                        {
548
4672
                            if (JSON_UNLIKELY(not sax->end_array()))
0
4673
                            {
0
4674
                                return false;
0
4675
                            }
548
4676
                            break;
548
4677
                        }
1.66k
4678
1.66k
4679
                        // remember we are now inside an array
1.11k
4680
                        states.push_back(true);
1.11k
4681
1.11k
4682
                        // parse values (no need to call get_token)
1.11k
4683
                        continue;
1.66k
4684
                    }
1.66k
4685
158k
4686
                    case token_type::value_float:
158k
4687
                    {
158k
4688
                        const auto res = m_lexer.get_number_float();
158k
4689
158k
4690
                        if (JSON_UNLIKELY(not std::isfinite(res)))
0
4691
                        {
0
4692
                            return sax->parse_error(m_lexer.get_position(),
0
4693
                                                    m_lexer.get_token_string(),
0
4694
                                                    out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
0
4695
                        }
158k
4696
                        else
158k
4697
                        {
158k
4698
                            if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
0
4699
                            {
0
4700
                                return false;
0
4701
                            }
158k
4702
                            break;
158k
4703
                        }
158k
4704
                    }
158k
4705
0
4706
                    case token_type::literal_false:
0
4707
                    {
0
4708
                        if (JSON_UNLIKELY(not sax->boolean(false)))
0
4709
                        {
0
4710
                            return false;
0
4711
                        }
0
4712
                        break;
0
4713
                    }
0
4714
1.11k
4715
                    case token_type::literal_null:
1.11k
4716
                    {
1.11k
4717
                        if (JSON_UNLIKELY(not sax->null()))
0
4718
                        {
0
4719
                            return false;
0
4720
                        }
1.11k
4721
                        break;
1.11k
4722
                    }
1.11k
4723
1.66k
4724
                    case token_type::literal_true:
1.66k
4725
                    {
1.66k
4726
                        if (JSON_UNLIKELY(not sax->boolean(true)))
0
4727
                        {
0
4728
                            return false;
0
4729
                        }
1.66k
4730
                        break;
1.66k
4731
                    }
1.66k
4732
25.3k
4733
                    case token_type::value_integer:
25.3k
4734
                    {
25.3k
4735
                        if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
0
4736
                        {
0
4737
                            return false;
0
4738
                        }
25.3k
4739
                        break;
25.3k
4740
                    }
25.3k
4741
169k
4742
                    case token_type::value_string:
169k
4743
                    {
169k
4744
                        if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))
0
4745
                        {
0
4746
                            return false;
0
4747
                        }
169k
4748
                        break;
169k
4749
                    }
169k
4750
212k
4751
                    case token_type::value_unsigned:
212k
4752
                    {
212k
4753
                        if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
0
4754
                        {
0
4755
                            return false;
0
4756
                        }
212k
4757
                        break;
212k
4758
                    }
212k
4759
0
4760
                    case token_type::parse_error:
0
4761
                    {
0
4762
                        // using "uninitialized" to avoid "expected" message
0
4763
                        return sax->parse_error(m_lexer.get_position(),
0
4764
                                                m_lexer.get_token_string(),
0
4765
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized)));
212k
4766
                    }
212k
4767
0
4768
                    default: // the last token was unexpected
0
4769
                    {
0
4770
                        return sax->parse_error(m_lexer.get_position(),
0
4771
                                                m_lexer.get_token_string(),
0
4772
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value)));
212k
4773
                    }
569k
4774
                }
710k
4775
            }
851k
4776
            else
141k
4777
            {
141k
4778
                skip_to_state_evaluation = false;
141k
4779
            }
851k
4780
851k
4781
            // we reached this line after we successfully parsed a value
710k
4782
            if (states.empty())
2.34k
4783
            {
2.34k
4784
                // empty stack: we reached the end of the hieararchy: done
2.34k
4785
                return true;
2.34k
4786
            }
710k
4787
            else
708k
4788
            {
708k
4789
                if (states.back())  // array
26.4k
4790
                {
26.4k
4791
                    // comma -> next value
26.4k
4792
                    if (get_token() == token_type::value_separator)
25.3k
4793
                    {
25.3k
4794
                        // parse a new value
25.3k
4795
                        get_token();
25.3k
4796
                        continue;
25.3k
4797
                    }
26.4k
4798
26.4k
4799
                    // closing ]
1.11k
4800
                    if (JSON_LIKELY(last_token == token_type::end_array))
1.11k
4801
                    {
1.11k
4802
                        if (JSON_UNLIKELY(not sax->end_array()))
0
4803
                        {
0
4804
                            return false;
0
4805
                        }
1.11k
4806
1.11k
4807
                        // We are done with this array. Before we can parse a
1.11k
4808
                        // new value, we need to evaluate the new state first.
1.11k
4809
                        // By setting skip_to_state_evaluation to false, we
1.11k
4810
                        // are effectively jumping to the beginning of this if.
1.11k
4811
                        assert(not states.empty());
1.11k
4812
                        states.pop_back();
1.11k
4813
                        skip_to_state_evaluation = true;
1.11k
4814
                        continue;
1.11k
4815
                    }
1.11k
4816
                    else
0
4817
                    {
0
4818
                        return sax->parse_error(m_lexer.get_position(),
0
4819
                                                m_lexer.get_token_string(),
0
4820
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array)));
0
4821
                    }
1.11k
4822
                }
708k
4823
                else  // object
681k
4824
                {
681k
4825
                    // comma -> next value
681k
4826
                    if (get_token() == token_type::value_separator)
541k
4827
                    {
541k
4828
                        // parse key
541k
4829
                        if (JSON_UNLIKELY(get_token() != token_type::value_string))
0
4830
                        {
0
4831
                            return sax->parse_error(m_lexer.get_position(),
0
4832
                                                    m_lexer.get_token_string(),
0
4833
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
0
4834
                        }
541k
4835
                        else
541k
4836
                        {
541k
4837
                            if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
0
4838
                            {
0
4839
                                return false;
0
4840
                            }
541k
4841
                        }
541k
4842
541k
4843
                        // parse separator (:)
541k
4844
                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))
0
4845
                        {
0
4846
                            return sax->parse_error(m_lexer.get_position(),
0
4847
                                                    m_lexer.get_token_string(),
0
4848
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
0
4849
                        }
541k
4850
541k
4851
                        // parse values
541k
4852
                        get_token();
541k
4853
                        continue;
541k
4854
                    }
681k
4855
681k
4856
                    // closing }
140k
4857
                    if (JSON_LIKELY(last_token == token_type::end_object))
140k
4858
                    {
140k
4859
                        if (JSON_UNLIKELY(not sax->end_object()))
0
4860
                        {
0
4861
                            return false;
0
4862
                        }
140k
4863
140k
4864
                        // We are done with this object. Before we can parse a
140k
4865
                        // new value, we need to evaluate the new state first.
140k
4866
                        // By setting skip_to_state_evaluation to false, we
140k
4867
                        // are effectively jumping to the beginning of this if.
140k
4868
                        assert(not states.empty());
140k
4869
                        states.pop_back();
140k
4870
                        skip_to_state_evaluation = true;
140k
4871
                        continue;
140k
4872
                    }
140k
4873
                    else
0
4874
                    {
0
4875
                        return sax->parse_error(m_lexer.get_position(),
0
4876
                                                m_lexer.get_token_string(),
0
4877
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
0
4878
                    }
140k
4879
                }
708k
4880
            }
710k
4881
        }
2.34k
4882
    }
_ZN8nlohmann6detail6parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE18sax_parse_internalINS0_19json_sax_dom_parserISC_EEEEbPT_
2.34k
4600
    {
2.34k
4601
        // stack to remember the hieararchy of structured values we are parsing
2.34k
4602
        // true = array; false = object
2.34k
4603
        std::vector<bool> states;
2.34k
4604
        // value to avoid a goto (see comment where set to true)
2.34k
4605
        bool skip_to_state_evaluation = false;
2.34k
4606
851k
4607
        while (true)
851k
4608
        {
851k
4609
            if (not skip_to_state_evaluation)
710k
4610
            {
710k
4611
                // invariant: get_token() was called before each iteration
569k
4612
                switch (last_token)
569k
4613
                {
140k
4614
                    case token_type::begin_object:
140k
4615
                    {
140k
4616
                        if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
0
4617
                        {
0
4618
                            return false;
0
4619
                        }
140k
4620
140k
4621
                        // closing } -> we are done
140k
4622
                        if (get_token() == token_type::end_object)
0
4623
                        {
0
4624
                            if (JSON_UNLIKELY(not sax->end_object()))
0
4625
                            {
0
4626
                                return false;
0
4627
                            }
0
4628
                            break;
0
4629
                        }
140k
4630
140k
4631
                        // parse key
140k
4632
                        if (JSON_UNLIKELY(last_token != token_type::value_string))
0
4633
                        {
0
4634
                            return sax->parse_error(m_lexer.get_position(),
0
4635
                                                    m_lexer.get_token_string(),
0
4636
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
0
4637
                        }
140k
4638
                        else
140k
4639
                        {
140k
4640
                            if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
0
4641
                            {
0
4642
                                return false;
0
4643
                            }
140k
4644
                        }
140k
4645
140k
4646
                        // parse separator (:)
140k
4647
                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))
0
4648
                        {
0
4649
                            return sax->parse_error(m_lexer.get_position(),
0
4650
                                                    m_lexer.get_token_string(),
0
4651
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
0
4652
                        }
140k
4653
140k
4654
                        // remember we are now inside an object
140k
4655
                        states.push_back(false);
140k
4656
140k
4657
                        // parse values
140k
4658
                        get_token();
140k
4659
                        continue;
140k
4660
                    }
140k
4661
1.66k
4662
                    case token_type::begin_array:
1.66k
4663
                    {
1.66k
4664
                        if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
0
4665
                        {
0
4666
                            return false;
0
4667
                        }
1.66k
4668
1.66k
4669
                        // closing ] -> we are done
1.66k
4670
                        if (get_token() == token_type::end_array)
548
4671
                        {
548
4672
                            if (JSON_UNLIKELY(not sax->end_array()))
0
4673
                            {
0
4674
                                return false;
0
4675
                            }
548
4676
                            break;
548
4677
                        }
1.66k
4678
1.66k
4679
                        // remember we are now inside an array
1.11k
4680
                        states.push_back(true);
1.11k
4681
1.11k
4682
                        // parse values (no need to call get_token)
1.11k
4683
                        continue;
1.66k
4684
                    }
1.66k
4685
158k
4686
                    case token_type::value_float:
158k
4687
                    {
158k
4688
                        const auto res = m_lexer.get_number_float();
158k
4689
158k
4690
                        if (JSON_UNLIKELY(not std::isfinite(res)))
0
4691
                        {
0
4692
                            return sax->parse_error(m_lexer.get_position(),
0
4693
                                                    m_lexer.get_token_string(),
0
4694
                                                    out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
0
4695
                        }
158k
4696
                        else
158k
4697
                        {
158k
4698
                            if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
0
4699
                            {
0
4700
                                return false;
0
4701
                            }
158k
4702
                            break;
158k
4703
                        }
158k
4704
                    }
158k
4705
0
4706
                    case token_type::literal_false:
0
4707
                    {
0
4708
                        if (JSON_UNLIKELY(not sax->boolean(false)))
0
4709
                        {
0
4710
                            return false;
0
4711
                        }
0
4712
                        break;
0
4713
                    }
0
4714
1.11k
4715
                    case token_type::literal_null:
1.11k
4716
                    {
1.11k
4717
                        if (JSON_UNLIKELY(not sax->null()))
0
4718
                        {
0
4719
                            return false;
0
4720
                        }
1.11k
4721
                        break;
1.11k
4722
                    }
1.11k
4723
1.66k
4724
                    case token_type::literal_true:
1.66k
4725
                    {
1.66k
4726
                        if (JSON_UNLIKELY(not sax->boolean(true)))
0
4727
                        {
0
4728
                            return false;
0
4729
                        }
1.66k
4730
                        break;
1.66k
4731
                    }
1.66k
4732
25.3k
4733
                    case token_type::value_integer:
25.3k
4734
                    {
25.3k
4735
                        if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
0
4736
                        {
0
4737
                            return false;
0
4738
                        }
25.3k
4739
                        break;
25.3k
4740
                    }
25.3k
4741
169k
4742
                    case token_type::value_string:
169k
4743
                    {
169k
4744
                        if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))
0
4745
                        {
0
4746
                            return false;
0
4747
                        }
169k
4748
                        break;
169k
4749
                    }
169k
4750
212k
4751
                    case token_type::value_unsigned:
212k
4752
                    {
212k
4753
                        if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
0
4754
                        {
0
4755
                            return false;
0
4756
                        }
212k
4757
                        break;
212k
4758
                    }
212k
4759
0
4760
                    case token_type::parse_error:
0
4761
                    {
0
4762
                        // using "uninitialized" to avoid "expected" message
0
4763
                        return sax->parse_error(m_lexer.get_position(),
0
4764
                                                m_lexer.get_token_string(),
0
4765
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized)));
212k
4766
                    }
212k
4767
0
4768
                    default: // the last token was unexpected
0
4769
                    {
0
4770
                        return sax->parse_error(m_lexer.get_position(),
0
4771
                                                m_lexer.get_token_string(),
0
4772
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value)));
212k
4773
                    }
569k
4774
                }
710k
4775
            }
851k
4776
            else
141k
4777
            {
141k
4778
                skip_to_state_evaluation = false;
141k
4779
            }
851k
4780
851k
4781
            // we reached this line after we successfully parsed a value
710k
4782
            if (states.empty())
2.34k
4783
            {
2.34k
4784
                // empty stack: we reached the end of the hieararchy: done
2.34k
4785
                return true;
2.34k
4786
            }
710k
4787
            else
708k
4788
            {
708k
4789
                if (states.back())  // array
26.4k
4790
                {
26.4k
4791
                    // comma -> next value
26.4k
4792
                    if (get_token() == token_type::value_separator)
25.3k
4793
                    {
25.3k
4794
                        // parse a new value
25.3k
4795
                        get_token();
25.3k
4796
                        continue;
25.3k
4797
                    }
26.4k
4798
26.4k
4799
                    // closing ]
1.11k
4800
                    if (JSON_LIKELY(last_token == token_type::end_array))
1.11k
4801
                    {
1.11k
4802
                        if (JSON_UNLIKELY(not sax->end_array()))
0
4803
                        {
0
4804
                            return false;
0
4805
                        }
1.11k
4806
1.11k
4807
                        // We are done with this array. Before we can parse a
1.11k
4808
                        // new value, we need to evaluate the new state first.
1.11k
4809
                        // By setting skip_to_state_evaluation to false, we
1.11k
4810
                        // are effectively jumping to the beginning of this if.
1.11k
4811
                        assert(not states.empty());
1.11k
4812
                        states.pop_back();
1.11k
4813
                        skip_to_state_evaluation = true;
1.11k
4814
                        continue;
1.11k
4815
                    }
1.11k
4816
                    else
0
4817
                    {
0
4818
                        return sax->parse_error(m_lexer.get_position(),
0
4819
                                                m_lexer.get_token_string(),
0
4820
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array)));
0
4821
                    }
1.11k
4822
                }
708k
4823
                else  // object
681k
4824
                {
681k
4825
                    // comma -> next value
681k
4826
                    if (get_token() == token_type::value_separator)
541k
4827
                    {
541k
4828
                        // parse key
541k
4829
                        if (JSON_UNLIKELY(get_token() != token_type::value_string))
0
4830
                        {
0
4831
                            return sax->parse_error(m_lexer.get_position(),
0
4832
                                                    m_lexer.get_token_string(),
0
4833
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
0
4834
                        }
541k
4835
                        else
541k
4836
                        {
541k
4837
                            if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
0
4838
                            {
0
4839
                                return false;
0
4840
                            }
541k
4841
                        }
541k
4842
541k
4843
                        // parse separator (:)
541k
4844
                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))
0
4845
                        {
0
4846
                            return sax->parse_error(m_lexer.get_position(),
0
4847
                                                    m_lexer.get_token_string(),
0
4848
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
0
4849
                        }
541k
4850
541k
4851
                        // parse values
541k
4852
                        get_token();
541k
4853
                        continue;
541k
4854
                    }
681k
4855
681k
4856
                    // closing }
140k
4857
                    if (JSON_LIKELY(last_token == token_type::end_object))
140k
4858
                    {
140k
4859
                        if (JSON_UNLIKELY(not sax->end_object()))
0
4860
                        {
0
4861
                            return false;
0
4862
                        }
140k
4863
140k
4864
                        // We are done with this object. Before we can parse a
140k
4865
                        // new value, we need to evaluate the new state first.
140k
4866
                        // By setting skip_to_state_evaluation to false, we
140k
4867
                        // are effectively jumping to the beginning of this if.
140k
4868
                        assert(not states.empty());
140k
4869
                        states.pop_back();
140k
4870
                        skip_to_state_evaluation = true;
140k
4871
                        continue;
140k
4872
                    }
140k
4873
                    else
0
4874
                    {
0
4875
                        return sax->parse_error(m_lexer.get_position(),
0
4876
                                                m_lexer.get_token_string(),
0
4877
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
0
4878
                    }
140k
4879
                }
708k
4880
            }
710k
4881
        }
2.34k
4882
    }
_ZN8nlohmann6detail6parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE18sax_parse_internalINS0_28json_sax_dom_callback_parserISC_EEEEbPT_
0
4600
    {
0
4601
        // stack to remember the hieararchy of structured values we are parsing
0
4602
        // true = array; false = object
0
4603
        std::vector<bool> states;
0
4604
        // value to avoid a goto (see comment where set to true)
0
4605
        bool skip_to_state_evaluation = false;
0
4606
0
4607
        while (true)
0
4608
        {
0
4609
            if (not skip_to_state_evaluation)
0
4610
            {
0
4611
                // invariant: get_token() was called before each iteration
0
4612
                switch (last_token)
0
4613
                {
0
4614
                    case token_type::begin_object:
0
4615
                    {
0
4616
                        if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
0
4617
                        {
0
4618
                            return false;
0
4619
                        }
0
4620
0
4621
                        // closing } -> we are done
0
4622
                        if (get_token() == token_type::end_object)
0
4623
                        {
0
4624
                            if (JSON_UNLIKELY(not sax->end_object()))
0
4625
                            {
0
4626
                                return false;
0
4627
                            }
0
4628
                            break;
0
4629
                        }
0
4630
0
4631
                        // parse key
0
4632
                        if (JSON_UNLIKELY(last_token != token_type::value_string))
0
4633
                        {
0
4634
                            return sax->parse_error(m_lexer.get_position(),
0
4635
                                                    m_lexer.get_token_string(),
0
4636
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
0
4637
                        }
0
4638
                        else
0
4639
                        {
0
4640
                            if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
0
4641
                            {
0
4642
                                return false;
0
4643
                            }
0
4644
                        }
0
4645
0
4646
                        // parse separator (:)
0
4647
                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))
0
4648
                        {
0
4649
                            return sax->parse_error(m_lexer.get_position(),
0
4650
                                                    m_lexer.get_token_string(),
0
4651
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
0
4652
                        }
0
4653
0
4654
                        // remember we are now inside an object
0
4655
                        states.push_back(false);
0
4656
0
4657
                        // parse values
0
4658
                        get_token();
0
4659
                        continue;
0
4660
                    }
0
4661
0
4662
                    case token_type::begin_array:
0
4663
                    {
0
4664
                        if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
0
4665
                        {
0
4666
                            return false;
0
4667
                        }
0
4668
0
4669
                        // closing ] -> we are done
0
4670
                        if (get_token() == token_type::end_array)
0
4671
                        {
0
4672
                            if (JSON_UNLIKELY(not sax->end_array()))
0
4673
                            {
0
4674
                                return false;
0
4675
                            }
0
4676
                            break;
0
4677
                        }
0
4678
0
4679
                        // remember we are now inside an array
0
4680
                        states.push_back(true);
0
4681
0
4682
                        // parse values (no need to call get_token)
0
4683
                        continue;
0
4684
                    }
0
4685
0
4686
                    case token_type::value_float:
0
4687
                    {
0
4688
                        const auto res = m_lexer.get_number_float();
0
4689
0
4690
                        if (JSON_UNLIKELY(not std::isfinite(res)))
0
4691
                        {
0
4692
                            return sax->parse_error(m_lexer.get_position(),
0
4693
                                                    m_lexer.get_token_string(),
0
4694
                                                    out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
0
4695
                        }
0
4696
                        else
0
4697
                        {
0
4698
                            if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
0
4699
                            {
0
4700
                                return false;
0
4701
                            }
0
4702
                            break;
0
4703
                        }
0
4704
                    }
0
4705
0
4706
                    case token_type::literal_false:
0
4707
                    {
0
4708
                        if (JSON_UNLIKELY(not sax->boolean(false)))
0
4709
                        {
0
4710
                            return false;
0
4711
                        }
0
4712
                        break;
0
4713
                    }
0
4714
0
4715
                    case token_type::literal_null:
0
4716
                    {
0
4717
                        if (JSON_UNLIKELY(not sax->null()))
0
4718
                        {
0
4719
                            return false;
0
4720
                        }
0
4721
                        break;
0
4722
                    }
0
4723
0
4724
                    case token_type::literal_true:
0
4725
                    {
0
4726
                        if (JSON_UNLIKELY(not sax->boolean(true)))
0
4727
                        {
0
4728
                            return false;
0
4729
                        }
0
4730
                        break;
0
4731
                    }
0
4732
0
4733
                    case token_type::value_integer:
0
4734
                    {
0
4735
                        if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
0
4736
                        {
0
4737
                            return false;
0
4738
                        }
0
4739
                        break;
0
4740
                    }
0
4741
0
4742
                    case token_type::value_string:
0
4743
                    {
0
4744
                        if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))
0
4745
                        {
0
4746
                            return false;
0
4747
                        }
0
4748
                        break;
0
4749
                    }
0
4750
0
4751
                    case token_type::value_unsigned:
0
4752
                    {
0
4753
                        if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
0
4754
                        {
0
4755
                            return false;
0
4756
                        }
0
4757
                        break;
0
4758
                    }
0
4759
0
4760
                    case token_type::parse_error:
0
4761
                    {
0
4762
                        // using "uninitialized" to avoid "expected" message
0
4763
                        return sax->parse_error(m_lexer.get_position(),
0
4764
                                                m_lexer.get_token_string(),
0
4765
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized)));
0
4766
                    }
0
4767
0
4768
                    default: // the last token was unexpected
0
4769
                    {
0
4770
                        return sax->parse_error(m_lexer.get_position(),
0
4771
                                                m_lexer.get_token_string(),
0
4772
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value)));
0
4773
                    }
0
4774
                }
0
4775
            }
0
4776
            else
0
4777
            {
0
4778
                skip_to_state_evaluation = false;
0
4779
            }
0
4780
0
4781
            // we reached this line after we successfully parsed a value
0
4782
            if (states.empty())
0
4783
            {
0
4784
                // empty stack: we reached the end of the hieararchy: done
0
4785
                return true;
0
4786
            }
0
4787
            else
0
4788
            {
0
4789
                if (states.back())  // array
0
4790
                {
0
4791
                    // comma -> next value
0
4792
                    if (get_token() == token_type::value_separator)
0
4793
                    {
0
4794
                        // parse a new value
0
4795
                        get_token();
0
4796
                        continue;
0
4797
                    }
0
4798
0
4799
                    // closing ]
0
4800
                    if (JSON_LIKELY(last_token == token_type::end_array))
0
4801
                    {
0
4802
                        if (JSON_UNLIKELY(not sax->end_array()))
0
4803
                        {
0
4804
                            return false;
0
4805
                        }
0
4806
0
4807
                        // We are done with this array. Before we can parse a
0
4808
                        // new value, we need to evaluate the new state first.
0
4809
                        // By setting skip_to_state_evaluation to false, we
0
4810
                        // are effectively jumping to the beginning of this if.
0
4811
                        assert(not states.empty());
0
4812
                        states.pop_back();
0
4813
                        skip_to_state_evaluation = true;
0
4814
                        continue;
0
4815
                    }
0
4816
                    else
0
4817
                    {
0
4818
                        return sax->parse_error(m_lexer.get_position(),
0
4819
                                                m_lexer.get_token_string(),
0
4820
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array)));
0
4821
                    }
0
4822
                }
0
4823
                else  // object
0
4824
                {
0
4825
                    // comma -> next value
0
4826
                    if (get_token() == token_type::value_separator)
0
4827
                    {
0
4828
                        // parse key
0
4829
                        if (JSON_UNLIKELY(get_token() != token_type::value_string))
0
4830
                        {
0
4831
                            return sax->parse_error(m_lexer.get_position(),
0
4832
                                                    m_lexer.get_token_string(),
0
4833
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
0
4834
                        }
0
4835
                        else
0
4836
                        {
0
4837
                            if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
0
4838
                            {
0
4839
                                return false;
0
4840
                            }
0
4841
                        }
0
4842
0
4843
                        // parse separator (:)
0
4844
                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))
0
4845
                        {
0
4846
                            return sax->parse_error(m_lexer.get_position(),
0
4847
                                                    m_lexer.get_token_string(),
0
4848
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
0
4849
                        }
0
4850
0
4851
                        // parse values
0
4852
                        get_token();
0
4853
                        continue;
0
4854
                    }
0
4855
0
4856
                    // closing }
0
4857
                    if (JSON_LIKELY(last_token == token_type::end_object))
0
4858
                    {
0
4859
                        if (JSON_UNLIKELY(not sax->end_object()))
0
4860
                        {
0
4861
                            return false;
0
4862
                        }
0
4863
0
4864
                        // We are done with this object. Before we can parse a
0
4865
                        // new value, we need to evaluate the new state first.
0
4866
                        // By setting skip_to_state_evaluation to false, we
0
4867
                        // are effectively jumping to the beginning of this if.
0
4868
                        assert(not states.empty());
0
4869
                        states.pop_back();
0
4870
                        skip_to_state_evaluation = true;
0
4871
                        continue;
0
4872
                    }
0
4873
                    else
0
4874
                    {
0
4875
                        return sax->parse_error(m_lexer.get_position(),
0
4876
                                                m_lexer.get_token_string(),
0
4877
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
0
4878
                    }
0
4879
                }
0
4880
            }
0
4881
        }
0
4882
    }
4883
4884
    /// get next token from lexer
4885
    token_type get_token()
2.78M
4886
    {
2.78M
4887
        return (last_token = m_lexer.scan());
2.78M
4888
    }
4889
4890
    std::string exception_message(const token_type expected)
0
4891
    {
0
4892
        std::string error_msg = "syntax error - ";
0
4893
        if (last_token == token_type::parse_error)
0
4894
        {
0
4895
            error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
0
4896
                         m_lexer.get_token_string() + "'";
0
4897
        }
0
4898
        else
0
4899
        {
0
4900
            error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
0
4901
        }
0
4902
0
4903
        if (expected != token_type::uninitialized)
0
4904
        {
0
4905
            error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
0
4906
        }
0
4907
0
4908
        return error_msg;
0
4909
    }
4910
4911
  private:
4912
    /// callback function
4913
    const parser_callback_t callback = nullptr;
4914
    /// the type of the last read token
4915
    token_type last_token = token_type::uninitialized;
4916
    /// the lexer
4917
    lexer_t m_lexer;
4918
    /// whether to throw exceptions in case of errors
4919
    const bool allow_exceptions = true;
4920
};
4921
}
4922
}
4923
4924
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
4925
4926
4927
#include <cstddef> // ptrdiff_t
4928
#include <limits>  // numeric_limits
4929
4930
namespace nlohmann
4931
{
4932
namespace detail
4933
{
4934
/*
4935
@brief an iterator for primitive JSON types
4936
4937
This class models an iterator for primitive JSON types (boolean, number,
4938
string). It's only purpose is to allow the iterator/const_iterator classes
4939
to "iterate" over primitive values. Internally, the iterator is modeled by
4940
a `difference_type` variable. Value begin_value (`0`) models the begin,
4941
end_value (`1`) models past the end.
4942
*/
4943
class primitive_iterator_t
4944
{
4945
  private:
4946
    using difference_type = std::ptrdiff_t;
4947
    static constexpr difference_type begin_value = 0;
4948
    static constexpr difference_type end_value = begin_value + 1;
4949
4950
    /// iterator as signed integer type
4951
    difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
4952
4953
  public:
4954
    constexpr difference_type get_value() const noexcept
0
4955
    {
0
4956
        return m_it;
0
4957
    }
4958
4959
    /// set iterator to a defined beginning
4960
    void set_begin() noexcept
0
4961
    {
0
4962
        m_it = begin_value;
0
4963
    }
4964
4965
    /// set iterator to a defined past the end
4966
    void set_end() noexcept
8
4967
    {
8
4968
        m_it = end_value;
8
4969
    }
4970
4971
    /// return whether the iterator can be dereferenced
4972
    constexpr bool is_begin() const noexcept
0
4973
    {
0
4974
        return m_it == begin_value;
0
4975
    }
4976
4977
    /// return whether the iterator is at end
4978
    constexpr bool is_end() const noexcept
0
4979
    {
0
4980
        return m_it == end_value;
0
4981
    }
4982
4983
    friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
4
4984
    {
4
4985
        return lhs.m_it == rhs.m_it;
4
4986
    }
4987
4988
    friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
4989
    {
4990
        return lhs.m_it < rhs.m_it;
4991
    }
4992
4993
    primitive_iterator_t operator+(difference_type n) noexcept
0
4994
    {
0
4995
        auto result = *this;
0
4996
        result += n;
0
4997
        return result;
0
4998
    }
4999
5000
    friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5001
    {
5002
        return lhs.m_it - rhs.m_it;
5003
    }
5004
5005
    primitive_iterator_t& operator++() noexcept
0
5006
    {
0
5007
        ++m_it;
0
5008
        return *this;
0
5009
    }
5010
5011
    primitive_iterator_t const operator++(int) noexcept
0
5012
    {
0
5013
        auto result = *this;
0
5014
        ++m_it;
0
5015
        return result;
0
5016
    }
5017
5018
    primitive_iterator_t& operator--() noexcept
0
5019
    {
0
5020
        --m_it;
0
5021
        return *this;
0
5022
    }
5023
5024
    primitive_iterator_t const operator--(int) noexcept
0
5025
    {
0
5026
        auto result = *this;
0
5027
        --m_it;
0
5028
        return result;
0
5029
    }
5030
5031
    primitive_iterator_t& operator+=(difference_type n) noexcept
0
5032
    {
0
5033
        m_it += n;
0
5034
        return *this;
0
5035
    }
5036
5037
    primitive_iterator_t& operator-=(difference_type n) noexcept
0
5038
    {
0
5039
        m_it -= n;
0
5040
        return *this;
0
5041
    }
5042
};
5043
}
5044
}
5045
5046
// #include <nlohmann/detail/iterators/internal_iterator.hpp>
5047
5048
5049
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
5050
5051
5052
namespace nlohmann
5053
{
5054
namespace detail
5055
{
5056
/*!
5057
@brief an iterator value
5058
5059
@note This structure could easily be a union, but MSVC currently does not allow
5060
unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
5061
*/
5062
template<typename BasicJsonType> struct internal_iterator
5063
{
5064
    /// iterator for JSON objects
5065
    typename BasicJsonType::object_t::iterator object_iterator {};
5066
    /// iterator for JSON arrays
5067
    typename BasicJsonType::array_t::iterator array_iterator {};
5068
    /// generic iterator for all other types
5069
    primitive_iterator_t primitive_iterator {};
5070
};
5071
}
5072
}
5073
5074
// #include <nlohmann/detail/iterators/iter_impl.hpp>
5075
5076
5077
#include <ciso646> // not
5078
#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
5079
#include <type_traits> // conditional, is_const, remove_const
5080
5081
// #include <nlohmann/detail/exceptions.hpp>
5082
5083
// #include <nlohmann/detail/iterators/internal_iterator.hpp>
5084
5085
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
5086
5087
// #include <nlohmann/detail/macro_scope.hpp>
5088
5089
// #include <nlohmann/detail/meta/cpp_future.hpp>
5090
5091
// #include <nlohmann/detail/value_t.hpp>
5092
5093
5094
namespace nlohmann
5095
{
5096
namespace detail
5097
{
5098
// forward declare, to be able to friend it later on
5099
template<typename IteratorType> class iteration_proxy;
5100
5101
/*!
5102
@brief a template for a bidirectional iterator for the @ref basic_json class
5103
5104
This class implements a both iterators (iterator and const_iterator) for the
5105
@ref basic_json class.
5106
5107
@note An iterator is called *initialized* when a pointer to a JSON value has
5108
      been set (e.g., by a constructor or a copy assignment). If the iterator is
5109
      default-constructed, it is *uninitialized* and most methods are undefined.
5110
      **The library uses assertions to detect calls on uninitialized iterators.**
5111
5112
@requirement The class satisfies the following concept requirements:
5113
-
5114
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
5115
  The iterator that can be moved can be moved in both directions (i.e.
5116
  incremented and decremented).
5117
5118
@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
5119
       iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
5120
*/
5121
template<typename BasicJsonType>
5122
class iter_impl
5123
{
5124
    /// allow basic_json to access private members
5125
    friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
5126
    friend BasicJsonType;
5127
    friend iteration_proxy<iter_impl>;
5128
5129
    using object_t = typename BasicJsonType::object_t;
5130
    using array_t = typename BasicJsonType::array_t;
5131
    // make sure BasicJsonType is basic_json or const basic_json
5132
    static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
5133
                  "iter_impl only accepts (const) basic_json");
5134
5135
  public:
5136
5137
    /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
5138
    /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
5139
    /// A user-defined iterator should provide publicly accessible typedefs named
5140
    /// iterator_category, value_type, difference_type, pointer, and reference.
5141
    /// Note that value_type is required to be non-const, even for constant iterators.
5142
    using iterator_category = std::bidirectional_iterator_tag;
5143
5144
    /// the type of the values when the iterator is dereferenced
5145
    using value_type = typename BasicJsonType::value_type;
5146
    /// a type to represent differences between iterators
5147
    using difference_type = typename BasicJsonType::difference_type;
5148
    /// defines a pointer to the type iterated over (value_type)
5149
    using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
5150
          typename BasicJsonType::const_pointer,
5151
          typename BasicJsonType::pointer>::type;
5152
    /// defines a reference to the type iterated over (value_type)
5153
    using reference =
5154
        typename std::conditional<std::is_const<BasicJsonType>::value,
5155
        typename BasicJsonType::const_reference,
5156
        typename BasicJsonType::reference>::type;
5157
5158
    /// default constructor
5159
    iter_impl() = default;
5160
5161
    /*!
5162
    @brief constructor for a given JSON instance
5163
    @param[in] object  pointer to a JSON object for this iterator
5164
    @pre object != nullptr
5165
    @post The iterator is initialized; i.e. `m_object != nullptr`.
5166
    */
5167
    explicit iter_impl(pointer object) noexcept : m_object(object)
7.06k
5168
    {
7.06k
5169
        assert(m_object != nullptr);
7.06k
5170
7.06k
5171
        switch (m_object->m_type)
7.06k
5172
        {
6.99k
5173
            case value_t::object:
6.99k
5174
            {
6.99k
5175
                m_it.object_iterator = typename object_t::iterator();
6.99k
5176
                break;
6.99k
5177
            }
6.99k
5178
64
5179
            case value_t::array:
64
5180
            {
64
5181
                m_it.array_iterator = typename array_t::iterator();
64
5182
                break;
6.99k
5183
            }
6.99k
5184
8
5185
            default:
8
5186
            {
8
5187
                m_it.primitive_iterator = primitive_iterator_t();
8
5188
                break;
6.99k
5189
            }
7.06k
5190
        }
7.06k
5191
    }
5192
5193
    /*!
5194
    @note The conventional copy constructor and copy assignment are implicitly
5195
          defined. Combined with the following converting constructor and
5196
          assignment, they support: (1) copy from iterator to iterator, (2)
5197
          copy from const iterator to const iterator, and (3) conversion from
5198
          iterator to const iterator. However conversion from const iterator
5199
          to iterator is not defined.
5200
    */
5201
5202
    /*!
5203
    @brief converting constructor
5204
    @param[in] other  non-const iterator to copy from
5205
    @note It is not checked whether @a other is initialized.
5206
    */
5207
    iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
0
5208
        : m_object(other.m_object), m_it(other.m_it) {}
5209
5210
    /*!
5211
    @brief converting assignment
5212
    @param[in,out] other  non-const iterator to copy from
5213
    @return const/non-const iterator
5214
    @note It is not checked whether @a other is initialized.
5215
    */
5216
    iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
5217
    {
5218
        m_object = other.m_object;
5219
        m_it = other.m_it;
5220
        return *this;
5221
    }
5222
5223
  private:
5224
    /*!
5225
    @brief set the iterator to the first value
5226
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5227
    */
5228
    void set_begin() noexcept
1.61k
5229
    {
1.61k
5230
        assert(m_object != nullptr);
1.61k
5231
1.61k
5232
        switch (m_object->m_type)
1.61k
5233
        {
1.58k
5234
            case value_t::object:
1.58k
5235
            {
1.58k
5236
                m_it.object_iterator = m_object->m_value.object->begin();
1.58k
5237
                break;
1.58k
5238
            }
1.58k
5239
32
5240
            case value_t::array:
32
5241
            {
32
5242
                m_it.array_iterator = m_object->m_value.array->begin();
32
5243
                break;
1.58k
5244
            }
1.58k
5245
0
5246
            case value_t::null:
0
5247
            {
0
5248
                // set to end so begin()==end() is true: null is empty
0
5249
                m_it.primitive_iterator.set_end();
0
5250
                break;
1.58k
5251
            }
1.58k
5252
0
5253
            default:
0
5254
            {
0
5255
                m_it.primitive_iterator.set_begin();
0
5256
                break;
1.58k
5257
            }
1.61k
5258
        }
1.61k
5259
    }
5260
5261
    /*!
5262
    @brief set the iterator past the last value
5263
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5264
    */
5265
    void set_end() noexcept
5.44k
5266
    {
5.44k
5267
        assert(m_object != nullptr);
5.44k
5268
5.44k
5269
        switch (m_object->m_type)
5.44k
5270
        {
5.40k
5271
            case value_t::object:
5.40k
5272
            {
5.40k
5273
                m_it.object_iterator = m_object->m_value.object->end();
5.40k
5274
                break;
5.40k
5275
            }
5.40k
5276
32
5277
            case value_t::array:
32
5278
            {
32
5279
                m_it.array_iterator = m_object->m_value.array->end();
32
5280
                break;
5.40k
5281
            }
5.40k
5282
8
5283
            default:
8
5284
            {
8
5285
                m_it.primitive_iterator.set_end();
8
5286
                break;
5.40k
5287
            }
5.44k
5288
        }
5.44k
5289
    }
5290
5291
  public:
5292
    /*!
5293
    @brief return a reference to the value pointed to by the iterator
5294
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5295
    */
5296
    reference operator*() const
4.31k
5297
    {
4.31k
5298
        assert(m_object != nullptr);
4.31k
5299
0
5300
        switch (m_object->m_type)
0
5301
        {
3.73k
5302
            case value_t::object:
3.73k
5303
            {
3.73k
5304
                assert(m_it.object_iterator != m_object->m_value.object->end());
3.73k
5305
                return m_it.object_iterator->second;
3.73k
5306
            }
3.73k
5307
584
5308
            case value_t::array:
584
5309
            {
584
5310
                assert(m_it.array_iterator != m_object->m_value.array->end());
584
5311
                return *m_it.array_iterator;
3.73k
5312
            }
3.73k
5313
0
5314
            case value_t::null:
0
5315
                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
3.73k
5316
0
5317
            default:
0
5318
            {
0
5319
                if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
0
5320
                {
0
5321
                    return *m_object;
0
5322
                }
0
5323
0
5324
                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
0
5325
            }
0
5326
        }
4.31k
5327
    }
5328
5329
    /*!
5330
    @brief dereference the iterator
5331
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5332
    */
5333
    pointer operator->() const
0
5334
    {
0
5335
        assert(m_object != nullptr);
0
5336
0
5337
        switch (m_object->m_type)
0
5338
        {
0
5339
            case value_t::object:
0
5340
            {
0
5341
                assert(m_it.object_iterator != m_object->m_value.object->end());
0
5342
                return &(m_it.object_iterator->second);
0
5343
            }
0
5344
0
5345
            case value_t::array:
0
5346
            {
0
5347
                assert(m_it.array_iterator != m_object->m_value.array->end());
0
5348
                return &*m_it.array_iterator;
0
5349
            }
0
5350
0
5351
            default:
0
5352
            {
0
5353
                if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
0
5354
                {
0
5355
                    return m_object;
0
5356
                }
0
5357
0
5358
                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
0
5359
            }
0
5360
        }
0
5361
    }
5362
5363
    /*!
5364
    @brief post-increment (it++)
5365
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5366
    */
5367
    iter_impl const operator++(int)
5368
    {
5369
        auto result = *this;
5370
        ++(*this);
5371
        return result;
5372
    }
5373
5374
    /*!
5375
    @brief pre-increment (++it)
5376
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5377
    */
5378
    iter_impl& operator++()
4.29k
5379
    {
4.29k
5380
        assert(m_object != nullptr);
4.29k
5381
4.29k
5382
        switch (m_object->m_type)
4.29k
5383
        {
3.71k
5384
            case value_t::object:
3.71k
5385
            {
3.71k
5386
                std::advance(m_it.object_iterator, 1);
3.71k
5387
                break;
3.71k
5388
            }
3.71k
5389
584
5390
            case value_t::array:
584
5391
            {
584
5392
                std::advance(m_it.array_iterator, 1);
584
5393
                break;
3.71k
5394
            }
3.71k
5395
0
5396
            default:
0
5397
            {
0
5398
                ++m_it.primitive_iterator;
0
5399
                break;
3.71k
5400
            }
4.29k
5401
        }
4.29k
5402
4.29k
5403
        return *this;
4.29k
5404
    }
5405
5406
    /*!
5407
    @brief post-decrement (it--)
5408
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5409
    */
5410
    iter_impl const operator--(int)
5411
    {
5412
        auto result = *this;
5413
        --(*this);
5414
        return result;
5415
    }
5416
5417
    /*!
5418
    @brief pre-decrement (--it)
5419
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5420
    */
5421
    iter_impl& operator--()
5422
    {
5423
        assert(m_object != nullptr);
5424
5425
        switch (m_object->m_type)
5426
        {
5427
            case value_t::object:
5428
            {
5429
                std::advance(m_it.object_iterator, -1);
5430
                break;
5431
            }
5432
5433
            case value_t::array:
5434
            {
5435
                std::advance(m_it.array_iterator, -1);
5436
                break;
5437
            }
5438
5439
            default:
5440
            {
5441
                --m_it.primitive_iterator;
5442
                break;
5443
            }
5444
        }
5445
5446
        return *this;
5447
    }
5448
5449
    /*!
5450
    @brief  comparison: equal
5451
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5452
    */
5453
    bool operator==(const iter_impl& other) const
5.97k
5454
    {
5.97k
5455
        // if objects are not the same, the comparison is undefined
5.97k
5456
        if (JSON_UNLIKELY(m_object != other.m_object))
0
5457
        {
0
5458
            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
0
5459
        }
5.97k
5460
5.97k
5461
        assert(m_object != nullptr);
5.97k
5462
0
5463
        switch (m_object->m_type)
0
5464
        {
5.35k
5465
            case value_t::object:
5.35k
5466
                return (m_it.object_iterator == other.m_it.object_iterator);
5.35k
5467
616
5468
            case value_t::array:
616
5469
                return (m_it.array_iterator == other.m_it.array_iterator);
5.35k
5470
4
5471
            default:
4
5472
                return (m_it.primitive_iterator == other.m_it.primitive_iterator);
0
5473
        }
5.97k
5474
    }
5475
5476
    /*!
5477
    @brief  comparison: not equal
5478
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5479
    */
5480
    bool operator!=(const iter_impl& other) const
5.97k
5481
    {
5.97k
5482
        return not operator==(other);
5.97k
5483
    }
5484
5485
    /*!
5486
    @brief  comparison: smaller
5487
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5488
    */
5489
    bool operator<(const iter_impl& other) const
5490
    {
5491
        // if objects are not the same, the comparison is undefined
5492
        if (JSON_UNLIKELY(m_object != other.m_object))
5493
        {
5494
            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
5495
        }
5496
5497
        assert(m_object != nullptr);
5498
5499
        switch (m_object->m_type)
5500
        {
5501
            case value_t::object:
5502
                JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
5503
5504
            case value_t::array:
5505
                return (m_it.array_iterator < other.m_it.array_iterator);
5506
5507
            default:
5508
                return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5509
        }
5510
    }
5511
5512
    /*!
5513
    @brief  comparison: less than or equal
5514
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5515
    */
5516
    bool operator<=(const iter_impl& other) const
5517
    {
5518
        return not other.operator < (*this);
5519
    }
5520
5521
    /*!
5522
    @brief  comparison: greater than
5523
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5524
    */
5525
    bool operator>(const iter_impl& other) const
5526
    {
5527
        return not operator<=(other);
5528
    }
5529
5530
    /*!
5531
    @brief  comparison: greater than or equal
5532
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5533
    */
5534
    bool operator>=(const iter_impl& other) const
5535
    {
5536
        return not operator<(other);
5537
    }
5538
5539
    /*!
5540
    @brief  add to iterator
5541
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5542
    */
5543
    iter_impl& operator+=(difference_type i)
5544
    {
5545
        assert(m_object != nullptr);
5546
5547
        switch (m_object->m_type)
5548
        {
5549
            case value_t::object:
5550
                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
5551
5552
            case value_t::array:
5553
            {
5554
                std::advance(m_it.array_iterator, i);
5555
                break;
5556
            }
5557
5558
            default:
5559
            {
5560
                m_it.primitive_iterator += i;
5561
                break;
5562
            }
5563
        }
5564
5565
        return *this;
5566
    }
5567
5568
    /*!
5569
    @brief  subtract from iterator
5570
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5571
    */
5572
    iter_impl& operator-=(difference_type i)
5573
    {
5574
        return operator+=(-i);
5575
    }
5576
5577
    /*!
5578
    @brief  add to iterator
5579
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5580
    */
5581
    iter_impl operator+(difference_type i) const
5582
    {
5583
        auto result = *this;
5584
        result += i;
5585
        return result;
5586
    }
5587
5588
    /*!
5589
    @brief  addition of distance and iterator
5590
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5591
    */
5592
    friend iter_impl operator+(difference_type i, const iter_impl& it)
5593
    {
5594
        auto result = it;
5595
        result += i;
5596
        return result;
5597
    }
5598
5599
    /*!
5600
    @brief  subtract from iterator
5601
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5602
    */
5603
    iter_impl operator-(difference_type i) const
5604
    {
5605
        auto result = *this;
5606
        result -= i;
5607
        return result;
5608
    }
5609
5610
    /*!
5611
    @brief  return difference
5612
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5613
    */
5614
    difference_type operator-(const iter_impl& other) const
5615
    {
5616
        assert(m_object != nullptr);
5617
5618
        switch (m_object->m_type)
5619
        {
5620
            case value_t::object:
5621
                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
5622
5623
            case value_t::array:
5624
                return m_it.array_iterator - other.m_it.array_iterator;
5625
5626
            default:
5627
                return m_it.primitive_iterator - other.m_it.primitive_iterator;
5628
        }
5629
    }
5630
5631
    /*!
5632
    @brief  access to successor
5633
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5634
    */
5635
    reference operator[](difference_type n) const
5636
    {
5637
        assert(m_object != nullptr);
5638
5639
        switch (m_object->m_type)
5640
        {
5641
            case value_t::object:
5642
                JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
5643
5644
            case value_t::array:
5645
                return *std::next(m_it.array_iterator, n);
5646
5647
            case value_t::null:
5648
                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5649
5650
            default:
5651
            {
5652
                if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n))
5653
                {
5654
                    return *m_object;
5655
                }
5656
5657
                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5658
            }
5659
        }
5660
    }
5661
5662
    /*!
5663
    @brief  return the key of an object iterator
5664
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5665
    */
5666
    const typename object_t::key_type& key() const
0
5667
    {
0
5668
        assert(m_object != nullptr);
0
5669
0
5670
        if (JSON_LIKELY(m_object->is_object()))
0
5671
        {
0
5672
            return m_it.object_iterator->first;
0
5673
        }
0
5674
0
5675
        JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
0
5676
    }
5677
5678
    /*!
5679
    @brief  return the value of an iterator
5680
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5681
    */
5682
    reference value() const
3.73k
5683
    {
3.73k
5684
        return operator*();
3.73k
5685
    }
5686
5687
  private:
5688
    /// associated JSON instance
5689
    pointer m_object = nullptr;
5690
    /// the actual iterator of the associated instance
5691
    internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it;
5692
};
5693
}
5694
}
5695
5696
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5697
5698
// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
5699
5700
5701
#include <cstddef> // ptrdiff_t
5702
#include <iterator> // reverse_iterator
5703
#include <utility> // declval
5704
5705
namespace nlohmann
5706
{
5707
namespace detail
5708
{
5709
//////////////////////
5710
// reverse_iterator //
5711
//////////////////////
5712
5713
/*!
5714
@brief a template for a reverse iterator class
5715
5716
@tparam Base the base iterator type to reverse. Valid types are @ref
5717
iterator (to create @ref reverse_iterator) and @ref const_iterator (to
5718
create @ref const_reverse_iterator).
5719
5720
@requirement The class satisfies the following concept requirements:
5721
-
5722
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
5723
  The iterator that can be moved can be moved in both directions (i.e.
5724
  incremented and decremented).
5725
- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
5726
  It is possible to write to the pointed-to element (only if @a Base is
5727
  @ref iterator).
5728
5729
@since version 1.0.0
5730
*/
5731
template<typename Base>
5732
class json_reverse_iterator : public std::reverse_iterator<Base>
5733
{
5734
  public:
5735
    using difference_type = std::ptrdiff_t;
5736
    /// shortcut to the reverse iterator adapter
5737
    using base_iterator = std::reverse_iterator<Base>;
5738
    /// the reference type for the pointed-to element
5739
    using reference = typename Base::reference;
5740
5741
    /// create reverse iterator from iterator
5742
    explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
5743
        : base_iterator(it) {}
5744
5745
    /// create reverse iterator from base class
5746
    explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
5747
5748
    /// post-increment (it++)
5749
    json_reverse_iterator const operator++(int)
5750
    {
5751
        return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
5752
    }
5753
5754
    /// pre-increment (++it)
5755
    json_reverse_iterator& operator++()
5756
    {
5757
        return static_cast<json_reverse_iterator&>(base_iterator::operator++());
5758
    }
5759
5760
    /// post-decrement (it--)
5761
    json_reverse_iterator const operator--(int)
5762
    {
5763
        return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
5764
    }
5765
5766
    /// pre-decrement (--it)
5767
    json_reverse_iterator& operator--()
5768
    {
5769
        return static_cast<json_reverse_iterator&>(base_iterator::operator--());
5770
    }
5771
5772
    /// add to iterator
5773
    json_reverse_iterator& operator+=(difference_type i)
5774
    {
5775
        return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
5776
    }
5777
5778
    /// add to iterator
5779
    json_reverse_iterator operator+(difference_type i) const
5780
    {
5781
        return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
5782
    }
5783
5784
    /// subtract from iterator
5785
    json_reverse_iterator operator-(difference_type i) const
5786
    {
5787
        return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
5788
    }
5789
5790
    /// return difference
5791
    difference_type operator-(const json_reverse_iterator& other) const
5792
    {
5793
        return base_iterator(*this) - base_iterator(other);
5794
    }
5795
5796
    /// access to successor
5797
    reference operator[](difference_type n) const
5798
    {
5799
        return *(this->operator+(n));
5800
    }
5801
5802
    /// return the key of an object iterator
5803
    auto key() const -> decltype(std::declval<Base>().key())
5804
    {
5805
        auto it = --this->base();
5806
        return it.key();
5807
    }
5808
5809
    /// return the value of an iterator
5810
    reference value() const
5811
    {
5812
        auto it = --this->base();
5813
        return it.operator * ();
5814
    }
5815
};
5816
}
5817
}
5818
5819
// #include <nlohmann/detail/output/output_adapters.hpp>
5820
5821
5822
#include <algorithm> // copy
5823
#include <cstddef> // size_t
5824
#include <ios> // streamsize
5825
#include <iterator> // back_inserter
5826
#include <memory> // shared_ptr, make_shared
5827
#include <ostream> // basic_ostream
5828
#include <string> // basic_string
5829
#include <vector> // vector
5830
5831
namespace nlohmann
5832
{
5833
namespace detail
5834
{
5835
/// abstract output adapter interface
5836
template<typename CharType> struct output_adapter_protocol
5837
{
5838
    virtual void write_character(CharType c) = 0;
5839
    virtual void write_characters(const CharType* s, std::size_t length) = 0;
440
5840
    virtual ~output_adapter_protocol() = default;
5841
};
5842
5843
/// a type to simplify interfaces
5844
template<typename CharType>
5845
using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
5846
5847
/// output adapter for byte vectors
5848
template<typename CharType>
5849
class output_vector_adapter : public output_adapter_protocol<CharType>
5850
{
5851
  public:
5852
    explicit output_vector_adapter(std::vector<CharType>& vec) : v(vec) {}
5853
5854
    void write_character(CharType c) override
5855
    {
5856
        v.push_back(c);
5857
    }
5858
5859
    void write_characters(const CharType* s, std::size_t length) override
5860
    {
5861
        std::copy(s, s + length, std::back_inserter(v));
5862
    }
5863
5864
  private:
5865
    std::vector<CharType>& v;
5866
};
5867
5868
/// output adapter for output streams
5869
template<typename CharType>
5870
class output_stream_adapter : public output_adapter_protocol<CharType>
5871
{
5872
  public:
372
5873
    explicit output_stream_adapter(std::basic_ostream<CharType>& s) : stream(s) {}
5874
5875
    void write_character(CharType c) override
27.4k
5876
    {
27.4k
5877
        stream.put(c);
27.4k
5878
    }
5879
5880
    void write_characters(const CharType* s, std::size_t length) override
38.3k
5881
    {
38.3k
5882
        stream.write(s, static_cast<std::streamsize>(length));
38.3k
5883
    }
5884
5885
  private:
5886
    std::basic_ostream<CharType>& stream;
5887
};
5888
5889
/// output adapter for basic_string
5890
template<typename CharType, typename StringType = std::basic_string<CharType>>
5891
class output_string_adapter : public output_adapter_protocol<CharType>
5892
{
5893
  public:
68
5894
    explicit output_string_adapter(StringType& s) : str(s) {}
5895
5896
    void write_character(CharType c) override
444
5897
    {
444
5898
        str.push_back(c);
444
5899
    }
5900
5901
    void write_characters(const CharType* s, std::size_t length) override
964
5902
    {
964
5903
        str.append(s, length);
964
5904
    }
5905
5906
  private:
5907
    StringType& str;
5908
};
5909
5910
template<typename CharType, typename StringType = std::basic_string<CharType>>
5911
class output_adapter
5912
{
5913
  public:
5914
    output_adapter(std::vector<CharType>& vec)
5915
        : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
5916
5917
    output_adapter(std::basic_ostream<CharType>& s)
372
5918
        : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
5919
5920
    output_adapter(StringType& s)
68
5921
        : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
5922
5923
    operator output_adapter_t<CharType>()
440
5924
    {
440
5925
        return oa;
440
5926
    }
5927
5928
  private:
5929
    output_adapter_t<CharType> oa = nullptr;
5930
};
5931
}
5932
}
5933
5934
// #include <nlohmann/detail/input/binary_reader.hpp>
5935
5936
5937
#include <algorithm> // generate_n
5938
#include <array> // array
5939
#include <cassert> // assert
5940
#include <cmath> // ldexp
5941
#include <cstddef> // size_t
5942
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
5943
#include <cstdio> // snprintf
5944
#include <cstring> // memcpy
5945
#include <iterator> // back_inserter
5946
#include <limits> // numeric_limits
5947
#include <string> // char_traits, string
5948
#include <utility> // make_pair, move
5949
5950
// #include <nlohmann/detail/input/input_adapters.hpp>
5951
5952
// #include <nlohmann/detail/input/json_sax.hpp>
5953
5954
// #include <nlohmann/detail/exceptions.hpp>
5955
5956
// #include <nlohmann/detail/macro_scope.hpp>
5957
5958
// #include <nlohmann/detail/meta/is_sax.hpp>
5959
5960
// #include <nlohmann/detail/value_t.hpp>
5961
5962
5963
namespace nlohmann
5964
{
5965
namespace detail
5966
{
5967
///////////////////
5968
// binary reader //
5969
///////////////////
5970
5971
/*!
5972
@brief deserialization of CBOR, MessagePack, and UBJSON values
5973
*/
5974
template<typename BasicJsonType, typename SAX = json_sax_dom_parser<BasicJsonType>>
5975
class binary_reader
5976
{
5977
    using number_integer_t = typename BasicJsonType::number_integer_t;
5978
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5979
    using number_float_t = typename BasicJsonType::number_float_t;
5980
    using string_t = typename BasicJsonType::string_t;
5981
    using json_sax_t = SAX;
5982
5983
  public:
5984
    /*!
5985
    @brief create a binary reader
5986
5987
    @param[in] adapter  input adapter to read from
5988
    */
5989
    explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
5990
    {
5991
        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
5992
        assert(ia);
5993
    }
5994
5995
    /*!
5996
    @param[in] format  the binary format to parse
5997
    @param[in] sax_    a SAX event processor
5998
    @param[in] strict  whether to expect the input to be consumed completed
5999
6000
    @return
6001
    */
6002
    bool sax_parse(const input_format_t format,
6003
                   json_sax_t* sax_,
6004
                   const bool strict = true)
6005
    {
6006
        sax = sax_;
6007
        bool result = false;
6008
6009
        switch (format)
6010
        {
6011
            case input_format_t::cbor:
6012
                result = parse_cbor_internal();
6013
                break;
6014
6015
            case input_format_t::msgpack:
6016
                result = parse_msgpack_internal();
6017
                break;
6018
6019
            case input_format_t::ubjson:
6020
                result = parse_ubjson_internal();
6021
                break;
6022
6023
            // LCOV_EXCL_START
6024
            default:
6025
                assert(false);
6026
                // LCOV_EXCL_STOP
6027
        }
6028
6029
        // strict mode: next byte must be EOF
6030
        if (result and strict)
6031
        {
6032
            if (format == input_format_t::ubjson)
6033
            {
6034
                get_ignore_noop();
6035
            }
6036
            else
6037
            {
6038
                get();
6039
            }
6040
6041
            if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
6042
            {
6043
                return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, "expected end of input"));
6044
            }
6045
        }
6046
6047
        return result;
6048
    }
6049
6050
    /*!
6051
    @brief determine system byte order
6052
6053
    @return true if and only if system's byte order is little endian
6054
6055
    @note from http://stackoverflow.com/a/1001328/266378
6056
    */
6057
    static constexpr bool little_endianess(int num = 1) noexcept
6058
    {
6059
        return (*reinterpret_cast<char*>(&num) == 1);
6060
    }
6061
6062
  private:
6063
    /*!
6064
    @param[in] get_char  whether a new character should be retrieved from the
6065
                         input (true, default) or whether the last read
6066
                         character should be considered instead
6067
6068
    @return whether a valid CBOR value was passed to the SAX parser
6069
    */
6070
    bool parse_cbor_internal(const bool get_char = true)
6071
    {
6072
        switch (get_char ? get() : current)
6073
        {
6074
            // EOF
6075
            case std::char_traits<char>::eof():
6076
                return unexpect_eof();
6077
6078
            // Integer 0x00..0x17 (0..23)
6079
            case 0x00:
6080
            case 0x01:
6081
            case 0x02:
6082
            case 0x03:
6083
            case 0x04:
6084
            case 0x05:
6085
            case 0x06:
6086
            case 0x07:
6087
            case 0x08:
6088
            case 0x09:
6089
            case 0x0A:
6090
            case 0x0B:
6091
            case 0x0C:
6092
            case 0x0D:
6093
            case 0x0E:
6094
            case 0x0F:
6095
            case 0x10:
6096
            case 0x11:
6097
            case 0x12:
6098
            case 0x13:
6099
            case 0x14:
6100
            case 0x15:
6101
            case 0x16:
6102
            case 0x17:
6103
                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
6104
6105
            case 0x18: // Unsigned integer (one-byte uint8_t follows)
6106
            {
6107
                uint8_t number;
6108
                return get_number(number) and sax->number_unsigned(number);
6109
            }
6110
6111
            case 0x19: // Unsigned integer (two-byte uint16_t follows)
6112
            {
6113
                uint16_t number;
6114
                return get_number(number) and sax->number_unsigned(number);
6115
            }
6116
6117
            case 0x1A: // Unsigned integer (four-byte uint32_t follows)
6118
            {
6119
                uint32_t number;
6120
                return get_number(number) and sax->number_unsigned(number);
6121
            }
6122
6123
            case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
6124
            {
6125
                uint64_t number;
6126
                return get_number(number) and sax->number_unsigned(number);
6127
            }
6128
6129
            // Negative integer -1-0x00..-1-0x17 (-1..-24)
6130
            case 0x20:
6131
            case 0x21:
6132
            case 0x22:
6133
            case 0x23:
6134
            case 0x24:
6135
            case 0x25:
6136
            case 0x26:
6137
            case 0x27:
6138
            case 0x28:
6139
            case 0x29:
6140
            case 0x2A:
6141
            case 0x2B:
6142
            case 0x2C:
6143
            case 0x2D:
6144
            case 0x2E:
6145
            case 0x2F:
6146
            case 0x30:
6147
            case 0x31:
6148
            case 0x32:
6149
            case 0x33:
6150
            case 0x34:
6151
            case 0x35:
6152
            case 0x36:
6153
            case 0x37:
6154
                return sax->number_integer(static_cast<int8_t>(0x20 - 1 - current));
6155
6156
            case 0x38: // Negative integer (one-byte uint8_t follows)
6157
            {
6158
                uint8_t number;
6159
                return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6160
            }
6161
6162
            case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
6163
            {
6164
                uint16_t number;
6165
                return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6166
            }
6167
6168
            case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
6169
            {
6170
                uint32_t number;
6171
                return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6172
            }
6173
6174
            case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
6175
            {
6176
                uint64_t number;
6177
                return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1)
6178
                        - static_cast<number_integer_t>(number));
6179
            }
6180
6181
            // UTF-8 string (0x00..0x17 bytes follow)
6182
            case 0x60:
6183
            case 0x61:
6184
            case 0x62:
6185
            case 0x63:
6186
            case 0x64:
6187
            case 0x65:
6188
            case 0x66:
6189
            case 0x67:
6190
            case 0x68:
6191
            case 0x69:
6192
            case 0x6A:
6193
            case 0x6B:
6194
            case 0x6C:
6195
            case 0x6D:
6196
            case 0x6E:
6197
            case 0x6F:
6198
            case 0x70:
6199
            case 0x71:
6200
            case 0x72:
6201
            case 0x73:
6202
            case 0x74:
6203
            case 0x75:
6204
            case 0x76:
6205
            case 0x77:
6206
            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
6207
            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
6208
            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
6209
            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
6210
            case 0x7F: // UTF-8 string (indefinite length)
6211
            {
6212
                string_t s;
6213
                return get_cbor_string(s) and sax->string(s);
6214
            }
6215
6216
            // array (0x00..0x17 data items follow)
6217
            case 0x80:
6218
            case 0x81:
6219
            case 0x82:
6220
            case 0x83:
6221
            case 0x84:
6222
            case 0x85:
6223
            case 0x86:
6224
            case 0x87:
6225
            case 0x88:
6226
            case 0x89:
6227
            case 0x8A:
6228
            case 0x8B:
6229
            case 0x8C:
6230
            case 0x8D:
6231
            case 0x8E:
6232
            case 0x8F:
6233
            case 0x90:
6234
            case 0x91:
6235
            case 0x92:
6236
            case 0x93:
6237
            case 0x94:
6238
            case 0x95:
6239
            case 0x96:
6240
            case 0x97:
6241
                return get_cbor_array(static_cast<std::size_t>(current & 0x1F));
6242
6243
            case 0x98: // array (one-byte uint8_t for n follows)
6244
            {
6245
                uint8_t len;
6246
                return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
6247
            }
6248
6249
            case 0x99: // array (two-byte uint16_t for n follow)
6250
            {
6251
                uint16_t len;
6252
                return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
6253
            }
6254
6255
            case 0x9A: // array (four-byte uint32_t for n follow)
6256
            {
6257
                uint32_t len;
6258
                return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
6259
            }
6260
6261
            case 0x9B: // array (eight-byte uint64_t for n follow)
6262
            {
6263
                uint64_t len;
6264
                return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
6265
            }
6266
6267
            case 0x9F: // array (indefinite length)
6268
                return get_cbor_array(std::size_t(-1));
6269
6270
            // map (0x00..0x17 pairs of data items follow)
6271
            case 0xA0:
6272
            case 0xA1:
6273
            case 0xA2:
6274
            case 0xA3:
6275
            case 0xA4:
6276
            case 0xA5:
6277
            case 0xA6:
6278
            case 0xA7:
6279
            case 0xA8:
6280
            case 0xA9:
6281
            case 0xAA:
6282
            case 0xAB:
6283
            case 0xAC:
6284
            case 0xAD:
6285
            case 0xAE:
6286
            case 0xAF:
6287
            case 0xB0:
6288
            case 0xB1:
6289
            case 0xB2:
6290
            case 0xB3:
6291
            case 0xB4:
6292
            case 0xB5:
6293
            case 0xB6:
6294
            case 0xB7:
6295
                return get_cbor_object(static_cast<std::size_t>(current & 0x1F));
6296
6297
            case 0xB8: // map (one-byte uint8_t for n follows)
6298
            {
6299
                uint8_t len;
6300
                return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
6301
            }
6302
6303
            case 0xB9: // map (two-byte uint16_t for n follow)
6304
            {
6305
                uint16_t len;
6306
                return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
6307
            }
6308
6309
            case 0xBA: // map (four-byte uint32_t for n follow)
6310
            {
6311
                uint32_t len;
6312
                return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
6313
            }
6314
6315
            case 0xBB: // map (eight-byte uint64_t for n follow)
6316
            {
6317
                uint64_t len;
6318
                return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
6319
            }
6320
6321
            case 0xBF: // map (indefinite length)
6322
                return get_cbor_object(std::size_t(-1));
6323
6324
            case 0xF4: // false
6325
                return sax->boolean(false);
6326
6327
            case 0xF5: // true
6328
                return sax->boolean(true);
6329
6330
            case 0xF6: // null
6331
                return sax->null();
6332
6333
            case 0xF9: // Half-Precision Float (two-byte IEEE 754)
6334
            {
6335
                const int byte1 = get();
6336
                if (JSON_UNLIKELY(not unexpect_eof()))
6337
                {
6338
                    return false;
6339
                }
6340
                const int byte2 = get();
6341
                if (JSON_UNLIKELY(not unexpect_eof()))
6342
                {
6343
                    return false;
6344
                }
6345
6346
                // code from RFC 7049, Appendix D, Figure 3:
6347
                // As half-precision floating-point numbers were only added
6348
                // to IEEE 754 in 2008, today's programming platforms often
6349
                // still only have limited support for them. It is very
6350
                // easy to include at least decoding support for them even
6351
                // without such support. An example of a small decoder for
6352
                // half-precision floating-point numbers in the C language
6353
                // is shown in Fig. 3.
6354
                const int half = (byte1 << 8) + byte2;
6355
                const double val = [&half]
6356
                {
6357
                    const int exp = (half >> 10) & 0x1F;
6358
                    const int mant = half & 0x3FF;
6359
                    assert(0 <= exp and exp <= 32);
6360
                    assert(0 <= mant and mant <= 1024);
6361
                    switch (exp)
6362
                    {
6363
                        case 0:
6364
                            return std::ldexp(mant, -24);
6365
                        case 31:
6366
                            return (mant == 0)
6367
                            ? std::numeric_limits<double>::infinity()
6368
                            : std::numeric_limits<double>::quiet_NaN();
6369
                        default:
6370
                            return std::ldexp(mant + 1024, exp - 25);
6371
                    }
6372
                }();
6373
                return sax->number_float((half & 0x8000) != 0
6374
                                         ? static_cast<number_float_t>(-val)
6375
                                         : static_cast<number_float_t>(val), "");
6376
            }
6377
6378
            case 0xFA: // Single-Precision Float (four-byte IEEE 754)
6379
            {
6380
                float number;
6381
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
6382
            }
6383
6384
            case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
6385
            {
6386
                double number;
6387
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
6388
            }
6389
6390
            default: // anything else (0xFF is handled inside the other types)
6391
            {
6392
                auto last_token = get_token_string();
6393
                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + last_token));
6394
            }
6395
        }
6396
    }
6397
6398
    /*!
6399
    @return whether a valid MessagePack value was passed to the SAX parser
6400
    */
6401
    bool parse_msgpack_internal()
6402
    {
6403
        switch (get())
6404
        {
6405
            // EOF
6406
            case std::char_traits<char>::eof():
6407
                return unexpect_eof();
6408
6409
            // positive fixint
6410
            case 0x00:
6411
            case 0x01:
6412
            case 0x02:
6413
            case 0x03:
6414
            case 0x04:
6415
            case 0x05:
6416
            case 0x06:
6417
            case 0x07:
6418
            case 0x08:
6419
            case 0x09:
6420
            case 0x0A:
6421
            case 0x0B:
6422
            case 0x0C:
6423
            case 0x0D:
6424
            case 0x0E:
6425
            case 0x0F:
6426
            case 0x10:
6427
            case 0x11:
6428
            case 0x12:
6429
            case 0x13:
6430
            case 0x14:
6431
            case 0x15:
6432
            case 0x16:
6433
            case 0x17:
6434
            case 0x18:
6435
            case 0x19:
6436
            case 0x1A:
6437
            case 0x1B:
6438
            case 0x1C:
6439
            case 0x1D:
6440
            case 0x1E:
6441
            case 0x1F:
6442
            case 0x20:
6443
            case 0x21:
6444
            case 0x22:
6445
            case 0x23:
6446
            case 0x24:
6447
            case 0x25:
6448
            case 0x26:
6449
            case 0x27:
6450
            case 0x28:
6451
            case 0x29:
6452
            case 0x2A:
6453
            case 0x2B:
6454
            case 0x2C:
6455
            case 0x2D:
6456
            case 0x2E:
6457
            case 0x2F:
6458
            case 0x30:
6459
            case 0x31:
6460
            case 0x32:
6461
            case 0x33:
6462
            case 0x34:
6463
            case 0x35:
6464
            case 0x36:
6465
            case 0x37:
6466
            case 0x38:
6467
            case 0x39:
6468
            case 0x3A:
6469
            case 0x3B:
6470
            case 0x3C:
6471
            case 0x3D:
6472
            case 0x3E:
6473
            case 0x3F:
6474
            case 0x40:
6475
            case 0x41:
6476
            case 0x42:
6477
            case 0x43:
6478
            case 0x44:
6479
            case 0x45:
6480
            case 0x46:
6481
            case 0x47:
6482
            case 0x48:
6483
            case 0x49:
6484
            case 0x4A:
6485
            case 0x4B:
6486
            case 0x4C:
6487
            case 0x4D:
6488
            case 0x4E:
6489
            case 0x4F:
6490
            case 0x50:
6491
            case 0x51:
6492
            case 0x52:
6493
            case 0x53:
6494
            case 0x54:
6495
            case 0x55:
6496
            case 0x56:
6497
            case 0x57:
6498
            case 0x58:
6499
            case 0x59:
6500
            case 0x5A:
6501
            case 0x5B:
6502
            case 0x5C:
6503
            case 0x5D:
6504
            case 0x5E:
6505
            case 0x5F:
6506
            case 0x60:
6507
            case 0x61:
6508
            case 0x62:
6509
            case 0x63:
6510
            case 0x64:
6511
            case 0x65:
6512
            case 0x66:
6513
            case 0x67:
6514
            case 0x68:
6515
            case 0x69:
6516
            case 0x6A:
6517
            case 0x6B:
6518
            case 0x6C:
6519
            case 0x6D:
6520
            case 0x6E:
6521
            case 0x6F:
6522
            case 0x70:
6523
            case 0x71:
6524
            case 0x72:
6525
            case 0x73:
6526
            case 0x74:
6527
            case 0x75:
6528
            case 0x76:
6529
            case 0x77:
6530
            case 0x78:
6531
            case 0x79:
6532
            case 0x7A:
6533
            case 0x7B:
6534
            case 0x7C:
6535
            case 0x7D:
6536
            case 0x7E:
6537
            case 0x7F:
6538
                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
6539
6540
            // fixmap
6541
            case 0x80:
6542
            case 0x81:
6543
            case 0x82:
6544
            case 0x83:
6545
            case 0x84:
6546
            case 0x85:
6547
            case 0x86:
6548
            case 0x87:
6549
            case 0x88:
6550
            case 0x89:
6551
            case 0x8A:
6552
            case 0x8B:
6553
            case 0x8C:
6554
            case 0x8D:
6555
            case 0x8E:
6556
            case 0x8F:
6557
                return get_msgpack_object(static_cast<std::size_t>(current & 0x0F));
6558
6559
            // fixarray
6560
            case 0x90:
6561
            case 0x91:
6562
            case 0x92:
6563
            case 0x93:
6564
            case 0x94:
6565
            case 0x95:
6566
            case 0x96:
6567
            case 0x97:
6568
            case 0x98:
6569
            case 0x99:
6570
            case 0x9A:
6571
            case 0x9B:
6572
            case 0x9C:
6573
            case 0x9D:
6574
            case 0x9E:
6575
            case 0x9F:
6576
                return get_msgpack_array(static_cast<std::size_t>(current & 0x0F));
6577
6578
            // fixstr
6579
            case 0xA0:
6580
            case 0xA1:
6581
            case 0xA2:
6582
            case 0xA3:
6583
            case 0xA4:
6584
            case 0xA5:
6585
            case 0xA6:
6586
            case 0xA7:
6587
            case 0xA8:
6588
            case 0xA9:
6589
            case 0xAA:
6590
            case 0xAB:
6591
            case 0xAC:
6592
            case 0xAD:
6593
            case 0xAE:
6594
            case 0xAF:
6595
            case 0xB0:
6596
            case 0xB1:
6597
            case 0xB2:
6598
            case 0xB3:
6599
            case 0xB4:
6600
            case 0xB5:
6601
            case 0xB6:
6602
            case 0xB7:
6603
            case 0xB8:
6604
            case 0xB9:
6605
            case 0xBA:
6606
            case 0xBB:
6607
            case 0xBC:
6608
            case 0xBD:
6609
            case 0xBE:
6610
            case 0xBF:
6611
            {
6612
                string_t s;
6613
                return get_msgpack_string(s) and sax->string(s);
6614
            }
6615
6616
            case 0xC0: // nil
6617
                return sax->null();
6618
6619
            case 0xC2: // false
6620
                return sax->boolean(false);
6621
6622
            case 0xC3: // true
6623
                return sax->boolean(true);
6624
6625
            case 0xCA: // float 32
6626
            {
6627
                float number;
6628
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
6629
            }
6630
6631
            case 0xCB: // float 64
6632
            {
6633
                double number;
6634
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
6635
            }
6636
6637
            case 0xCC: // uint 8
6638
            {
6639
                uint8_t number;
6640
                return get_number(number) and sax->number_unsigned(number);
6641
            }
6642
6643
            case 0xCD: // uint 16
6644
            {
6645
                uint16_t number;
6646
                return get_number(number) and sax->number_unsigned(number);
6647
            }
6648
6649
            case 0xCE: // uint 32
6650
            {
6651
                uint32_t number;
6652
                return get_number(number) and sax->number_unsigned(number);
6653
            }
6654
6655
            case 0xCF: // uint 64
6656
            {
6657
                uint64_t number;
6658
                return get_number(number) and sax->number_unsigned(number);
6659
            }
6660
6661
            case 0xD0: // int 8
6662
            {
6663
                int8_t number;
6664
                return get_number(number) and sax->number_integer(number);
6665
            }
6666
6667
            case 0xD1: // int 16
6668
            {
6669
                int16_t number;
6670
                return get_number(number) and sax->number_integer(number);
6671
            }
6672
6673
            case 0xD2: // int 32
6674
            {
6675
                int32_t number;
6676
                return get_number(number) and sax->number_integer(number);
6677
            }
6678
6679
            case 0xD3: // int 64
6680
            {
6681
                int64_t number;
6682
                return get_number(number) and sax->number_integer(number);
6683
            }
6684
6685
            case 0xD9: // str 8
6686
            case 0xDA: // str 16
6687
            case 0xDB: // str 32
6688
            {
6689
                string_t s;
6690
                return get_msgpack_string(s) and sax->string(s);
6691
            }
6692
6693
            case 0xDC: // array 16
6694
            {
6695
                uint16_t len;
6696
                return get_number(len) and get_msgpack_array(static_cast<std::size_t>(len));
6697
            }
6698
6699
            case 0xDD: // array 32
6700
            {
6701
                uint32_t len;
6702
                return get_number(len) and get_msgpack_array(static_cast<std::size_t>(len));
6703
            }
6704
6705
            case 0xDE: // map 16
6706
            {
6707
                uint16_t len;
6708
                return get_number(len) and get_msgpack_object(static_cast<std::size_t>(len));
6709
            }
6710
6711
            case 0xDF: // map 32
6712
            {
6713
                uint32_t len;
6714
                return get_number(len) and get_msgpack_object(static_cast<std::size_t>(len));
6715
            }
6716
6717
            // negative fixint
6718
            case 0xE0:
6719
            case 0xE1:
6720
            case 0xE2:
6721
            case 0xE3:
6722
            case 0xE4:
6723
            case 0xE5:
6724
            case 0xE6:
6725
            case 0xE7:
6726
            case 0xE8:
6727
            case 0xE9:
6728
            case 0xEA:
6729
            case 0xEB:
6730
            case 0xEC:
6731
            case 0xED:
6732
            case 0xEE:
6733
            case 0xEF:
6734
            case 0xF0:
6735
            case 0xF1:
6736
            case 0xF2:
6737
            case 0xF3:
6738
            case 0xF4:
6739
            case 0xF5:
6740
            case 0xF6:
6741
            case 0xF7:
6742
            case 0xF8:
6743
            case 0xF9:
6744
            case 0xFA:
6745
            case 0xFB:
6746
            case 0xFC:
6747
            case 0xFD:
6748
            case 0xFE:
6749
            case 0xFF:
6750
                return sax->number_integer(static_cast<int8_t>(current));
6751
6752
            default: // anything else
6753
            {
6754
                auto last_token = get_token_string();
6755
                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading MessagePack; last byte: 0x" + last_token));
6756
            }
6757
        }
6758
    }
6759
6760
    /*!
6761
    @param[in] get_char  whether a new character should be retrieved from the
6762
                         input (true, default) or whether the last read
6763
                         character should be considered instead
6764
6765
    @return whether a valid UBJSON value was passed to the SAX parser
6766
    */
6767
    bool parse_ubjson_internal(const bool get_char = true)
6768
    {
6769
        return get_ubjson_value(get_char ? get_ignore_noop() : current);
6770
    }
6771
6772
    /*!
6773
    @brief get next character from the input
6774
6775
    This function provides the interface to the used input adapter. It does
6776
    not throw in case the input reached EOF, but returns a -'ve valued
6777
    `std::char_traits<char>::eof()` in that case.
6778
6779
    @return character read from the input
6780
    */
6781
    int get()
6782
    {
6783
        ++chars_read;
6784
        return (current = ia->get_character());
6785
    }
6786
6787
    /*!
6788
    @return character read from the input after ignoring all 'N' entries
6789
    */
6790
    int get_ignore_noop()
6791
    {
6792
        do
6793
        {
6794
            get();
6795
        }
6796
        while (current == 'N');
6797
6798
        return current;
6799
    }
6800
6801
    /*
6802
    @brief read a number from the input
6803
6804
    @tparam NumberType the type of the number
6805
    @param[out] result  number of type @a NumberType
6806
6807
    @return whether conversion completed
6808
6809
    @note This function needs to respect the system's endianess, because
6810
          bytes in CBOR, MessagePack, and UBJSON are stored in network order
6811
          (big endian) and therefore need reordering on little endian systems.
6812
    */
6813
    template<typename NumberType>
6814
    bool get_number(NumberType& result)
6815
    {
6816
        // step 1: read input into array with system's byte order
6817
        std::array<uint8_t, sizeof(NumberType)> vec;
6818
        for (std::size_t i = 0; i < sizeof(NumberType); ++i)
6819
        {
6820
            get();
6821
            if (JSON_UNLIKELY(not unexpect_eof()))
6822
            {
6823
                return false;
6824
            }
6825
6826
            // reverse byte order prior to conversion if necessary
6827
            if (is_little_endian)
6828
            {
6829
                vec[sizeof(NumberType) - i - 1] = static_cast<uint8_t>(current);
6830
            }
6831
            else
6832
            {
6833
                vec[i] = static_cast<uint8_t>(current); // LCOV_EXCL_LINE
6834
            }
6835
        }
6836
6837
        // step 2: convert array into number of type T and return
6838
        std::memcpy(&result, vec.data(), sizeof(NumberType));
6839
        return true;
6840
    }
6841
6842
    /*!
6843
    @brief create a string by reading characters from the input
6844
6845
    @tparam NumberType the type of the number
6846
    @param[in] len number of characters to read
6847
    @param[out] string created by reading @a len bytes
6848
6849
    @return whether string creation completed
6850
6851
    @note We can not reserve @a len bytes for the result, because @a len
6852
          may be too large. Usually, @ref unexpect_eof() detects the end of
6853
          the input before we run out of string memory.
6854
    */
6855
    template<typename NumberType>
6856
    bool get_string(const NumberType len, string_t& result)
6857
    {
6858
        bool success = true;
6859
        std::generate_n(std::back_inserter(result), len, [this, &success]()
6860
        {
6861
            get();
6862
            if (JSON_UNLIKELY(not unexpect_eof()))
6863
            {
6864
                success = false;
6865
            }
6866
            return static_cast<char>(current);
6867
        });
6868
        return success;
6869
    }
6870
6871
    /*!
6872
    @brief reads a CBOR string
6873
6874
    This function first reads starting bytes to determine the expected
6875
    string length and then copies this number of bytes into a string.
6876
    Additionally, CBOR's strings with indefinite lengths are supported.
6877
6878
    @param[out] result  created string
6879
6880
    @return whether string creation completed
6881
    */
6882
    bool get_cbor_string(string_t& result)
6883
    {
6884
        if (JSON_UNLIKELY(not unexpect_eof()))
6885
        {
6886
            return false;
6887
        }
6888
6889
        switch (current)
6890
        {
6891
            // UTF-8 string (0x00..0x17 bytes follow)
6892
            case 0x60:
6893
            case 0x61:
6894
            case 0x62:
6895
            case 0x63:
6896
            case 0x64:
6897
            case 0x65:
6898
            case 0x66:
6899
            case 0x67:
6900
            case 0x68:
6901
            case 0x69:
6902
            case 0x6A:
6903
            case 0x6B:
6904
            case 0x6C:
6905
            case 0x6D:
6906
            case 0x6E:
6907
            case 0x6F:
6908
            case 0x70:
6909
            case 0x71:
6910
            case 0x72:
6911
            case 0x73:
6912
            case 0x74:
6913
            case 0x75:
6914
            case 0x76:
6915
            case 0x77:
6916
            {
6917
                return get_string(current & 0x1F, result);
6918
            }
6919
6920
            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
6921
            {
6922
                uint8_t len;
6923
                return get_number(len) and get_string(len, result);
6924
            }
6925
6926
            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
6927
            {
6928
                uint16_t len;
6929
                return get_number(len) and get_string(len, result);
6930
            }
6931
6932
            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
6933
            {
6934
                uint32_t len;
6935
                return get_number(len) and get_string(len, result);
6936
            }
6937
6938
            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
6939
            {
6940
                uint64_t len;
6941
                return get_number(len) and get_string(len, result);
6942
            }
6943
6944
            case 0x7F: // UTF-8 string (indefinite length)
6945
            {
6946
                while (get() != 0xFF)
6947
                {
6948
                    string_t chunk;
6949
                    if (not get_cbor_string(chunk))
6950
                    {
6951
                        return false;
6952
                    }
6953
                    result.append(chunk);
6954
                }
6955
                return true;
6956
            }
6957
6958
            default:
6959
            {
6960
                auto last_token = get_token_string();
6961
                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a CBOR string; last byte: 0x" + last_token));
6962
            }
6963
        }
6964
    }
6965
6966
    /*!
6967
    @param[in] len  the length of the array or std::size_t(-1) for an
6968
                    array of indefinite size
6969
    @return whether array creation completed
6970
    */
6971
    bool get_cbor_array(const std::size_t len)
6972
    {
6973
        if (JSON_UNLIKELY(not sax->start_array(len)))
6974
        {
6975
            return false;
6976
        }
6977
6978
        if (len != std::size_t(-1))
6979
            for (std::size_t i = 0; i < len; ++i)
6980
            {
6981
                if (JSON_UNLIKELY(not parse_cbor_internal()))
6982
                {
6983
                    return false;
6984
                }
6985
            }
6986
        else
6987
        {
6988
            while (get() != 0xFF)
6989
            {
6990
                if (JSON_UNLIKELY(not parse_cbor_internal(false)))
6991
                {
6992
                    return false;
6993
                }
6994
            }
6995
        }
6996
6997
        return sax->end_array();
6998
    }
6999
7000
    /*!
7001
    @param[in] len  the length of the object or std::size_t(-1) for an
7002
                    object of indefinite size
7003
    @return whether object creation completed
7004
    */
7005
    bool get_cbor_object(const std::size_t len)
7006
    {
7007
        if (not JSON_UNLIKELY(sax->start_object(len)))
7008
        {
7009
            return false;
7010
        }
7011
7012
        string_t key;
7013
        if (len != std::size_t(-1))
7014
        {
7015
            for (std::size_t i = 0; i < len; ++i)
7016
            {
7017
                get();
7018
                if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
7019
                {
7020
                    return false;
7021
                }
7022
7023
                if (JSON_UNLIKELY(not parse_cbor_internal()))
7024
                {
7025
                    return false;
7026
                }
7027
                key.clear();
7028
            }
7029
        }
7030
        else
7031
        {
7032
            while (get() != 0xFF)
7033
            {
7034
                if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
7035
                {
7036
                    return false;
7037
                }
7038
7039
                if (JSON_UNLIKELY(not parse_cbor_internal()))
7040
                {
7041
                    return false;
7042
                }
7043
                key.clear();
7044
            }
7045
        }
7046
7047
        return sax->end_object();
7048
    }
7049
7050
    /*!
7051
    @brief reads a MessagePack string
7052
7053
    This function first reads starting bytes to determine the expected
7054
    string length and then copies this number of bytes into a string.
7055
7056
    @param[out] result  created string
7057
7058
    @return whether string creation completed
7059
    */
7060
    bool get_msgpack_string(string_t& result)
7061
    {
7062
        if (JSON_UNLIKELY(not unexpect_eof()))
7063
        {
7064
            return false;
7065
        }
7066
7067
        switch (current)
7068
        {
7069
            // fixstr
7070
            case 0xA0:
7071
            case 0xA1:
7072
            case 0xA2:
7073
            case 0xA3:
7074
            case 0xA4:
7075
            case 0xA5:
7076
            case 0xA6:
7077
            case 0xA7:
7078
            case 0xA8:
7079
            case 0xA9:
7080
            case 0xAA:
7081
            case 0xAB:
7082
            case 0xAC:
7083
            case 0xAD:
7084
            case 0xAE:
7085
            case 0xAF:
7086
            case 0xB0:
7087
            case 0xB1:
7088
            case 0xB2:
7089
            case 0xB3:
7090
            case 0xB4:
7091
            case 0xB5:
7092
            case 0xB6:
7093
            case 0xB7:
7094
            case 0xB8:
7095
            case 0xB9:
7096
            case 0xBA:
7097
            case 0xBB:
7098
            case 0xBC:
7099
            case 0xBD:
7100
            case 0xBE:
7101
            case 0xBF:
7102
            {
7103
                return get_string(current & 0x1F, result);
7104
            }
7105
7106
            case 0xD9: // str 8
7107
            {
7108
                uint8_t len;
7109
                return get_number(len) and get_string(len, result);
7110
            }
7111
7112
            case 0xDA: // str 16
7113
            {
7114
                uint16_t len;
7115
                return get_number(len) and get_string(len, result);
7116
            }
7117
7118
            case 0xDB: // str 32
7119
            {
7120
                uint32_t len;
7121
                return get_number(len) and get_string(len, result);
7122
            }
7123
7124
            default:
7125
            {
7126
                auto last_token = get_token_string();
7127
                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a MessagePack string; last byte: 0x" + last_token));
7128
            }
7129
        }
7130
    }
7131
7132
    /*!
7133
    @param[in] len  the length of the array
7134
    @return whether array creation completed
7135
    */
7136
    bool get_msgpack_array(const std::size_t len)
7137
    {
7138
        if (JSON_UNLIKELY(not sax->start_array(len)))
7139
        {
7140
            return false;
7141
        }
7142
7143
        for (std::size_t i = 0; i < len; ++i)
7144
        {
7145
            if (JSON_UNLIKELY(not parse_msgpack_internal()))
7146
            {
7147
                return false;
7148
            }
7149
        }
7150
7151
        return sax->end_array();
7152
    }
7153
7154
    /*!
7155
    @param[in] len  the length of the object
7156
    @return whether object creation completed
7157
    */
7158
    bool get_msgpack_object(const std::size_t len)
7159
    {
7160
        if (JSON_UNLIKELY(not sax->start_object(len)))
7161
        {
7162
            return false;
7163
        }
7164
7165
        string_t key;
7166
        for (std::size_t i = 0; i < len; ++i)
7167
        {
7168
            get();
7169
            if (JSON_UNLIKELY(not get_msgpack_string(key) or not sax->key(key)))
7170
            {
7171
                return false;
7172
            }
7173
7174
            if (JSON_UNLIKELY(not parse_msgpack_internal()))
7175
            {
7176
                return false;
7177
            }
7178
            key.clear();
7179
        }
7180
7181
        return sax->end_object();
7182
    }
7183
7184
    /*!
7185
    @brief reads a UBJSON string
7186
7187
    This function is either called after reading the 'S' byte explicitly
7188
    indicating a string, or in case of an object key where the 'S' byte can be
7189
    left out.
7190
7191
    @param[out] result   created string
7192
    @param[in] get_char  whether a new character should be retrieved from the
7193
                         input (true, default) or whether the last read
7194
                         character should be considered instead
7195
7196
    @return whether string creation completed
7197
    */
7198
    bool get_ubjson_string(string_t& result, const bool get_char = true)
7199
    {
7200
        if (get_char)
7201
        {
7202
            get();  // TODO: may we ignore N here?
7203
        }
7204
7205
        if (JSON_UNLIKELY(not unexpect_eof()))
7206
        {
7207
            return false;
7208
        }
7209
7210
        switch (current)
7211
        {
7212
            case 'U':
7213
            {
7214
                uint8_t len;
7215
                return get_number(len) and get_string(len, result);
7216
            }
7217
7218
            case 'i':
7219
            {
7220
                int8_t len;
7221
                return get_number(len) and get_string(len, result);
7222
            }
7223
7224
            case 'I':
7225
            {
7226
                int16_t len;
7227
                return get_number(len) and get_string(len, result);
7228
            }
7229
7230
            case 'l':
7231
            {
7232
                int32_t len;
7233
                return get_number(len) and get_string(len, result);
7234
            }
7235
7236
            case 'L':
7237
            {
7238
                int64_t len;
7239
                return get_number(len) and get_string(len, result);
7240
            }
7241
7242
            default:
7243
                auto last_token = get_token_string();
7244
                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a UBJSON string; last byte: 0x" + last_token));
7245
        }
7246
    }
7247
7248
    /*!
7249
    @param[out] result  determined size
7250
    @return whether size determination completed
7251
    */
7252
    bool get_ubjson_size_value(std::size_t& result)
7253
    {
7254
        switch (get_ignore_noop())
7255
        {
7256
            case 'U':
7257
            {
7258
                uint8_t number;
7259
                if (JSON_UNLIKELY(not get_number(number)))
7260
                {
7261
                    return false;
7262
                }
7263
                result = static_cast<std::size_t>(number);
7264
                return true;
7265
            }
7266
7267
            case 'i':
7268
            {
7269
                int8_t number;
7270
                if (JSON_UNLIKELY(not get_number(number)))
7271
                {
7272
                    return false;
7273
                }
7274
                result = static_cast<std::size_t>(number);
7275
                return true;
7276
            }
7277
7278
            case 'I':
7279
            {
7280
                int16_t number;
7281
                if (JSON_UNLIKELY(not get_number(number)))
7282
                {
7283
                    return false;
7284
                }
7285
                result = static_cast<std::size_t>(number);
7286
                return true;
7287
            }
7288
7289
            case 'l':
7290
            {
7291
                int32_t number;
7292
                if (JSON_UNLIKELY(not get_number(number)))
7293
                {
7294
                    return false;
7295
                }
7296
                result = static_cast<std::size_t>(number);
7297
                return true;
7298
            }
7299
7300
            case 'L':
7301
            {
7302
                int64_t number;
7303
                if (JSON_UNLIKELY(not get_number(number)))
7304
                {
7305
                    return false;
7306
                }
7307
                result = static_cast<std::size_t>(number);
7308
                return true;
7309
            }
7310
7311
            default:
7312
            {
7313
                auto last_token = get_token_string();
7314
                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "byte after '#' must denote a number type; last byte: 0x" + last_token));
7315
            }
7316
        }
7317
    }
7318
7319
    /*!
7320
    @brief determine the type and size for a container
7321
7322
    In the optimized UBJSON format, a type and a size can be provided to allow
7323
    for a more compact representation.
7324
7325
    @param[out] result  pair of the size and the type
7326
7327
    @return whether pair creation completed
7328
    */
7329
    bool get_ubjson_size_type(std::pair<std::size_t, int>& result)
7330
    {
7331
        result.first = string_t::npos; // size
7332
        result.second = 0; // type
7333
7334
        get_ignore_noop();
7335
7336
        if (current == '$')
7337
        {
7338
            result.second = get();  // must not ignore 'N', because 'N' maybe the type
7339
            if (JSON_UNLIKELY(not unexpect_eof()))
7340
            {
7341
                return false;
7342
            }
7343
7344
            get_ignore_noop();
7345
            if (JSON_UNLIKELY(current != '#'))
7346
            {
7347
                if (JSON_UNLIKELY(not unexpect_eof()))
7348
                {
7349
                    return false;
7350
                }
7351
                auto last_token = get_token_string();
7352
                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "expected '#' after UBJSON type information; last byte: 0x" + last_token));
7353
            }
7354
7355
            return get_ubjson_size_value(result.first);
7356
        }
7357
        else if (current == '#')
7358
        {
7359
            return get_ubjson_size_value(result.first);
7360
        }
7361
        return true;
7362
    }
7363
7364
    /*!
7365
    @param prefix  the previously read or set type prefix
7366
    @return whether value creation completed
7367
    */
7368
    bool get_ubjson_value(const int prefix)
7369
    {
7370
        switch (prefix)
7371
        {
7372
            case std::char_traits<char>::eof():  // EOF
7373
                return unexpect_eof();
7374
7375
            case 'T':  // true
7376
                return sax->boolean(true);
7377
            case 'F':  // false
7378
                return sax->boolean(false);
7379
7380
            case 'Z':  // null
7381
                return sax->null();
7382
7383
            case 'U':
7384
            {
7385
                uint8_t number;
7386
                return get_number(number) and sax->number_unsigned(number);
7387
            }
7388
7389
            case 'i':
7390
            {
7391
                int8_t number;
7392
                return get_number(number) and sax->number_integer(number);
7393
            }
7394
7395
            case 'I':
7396
            {
7397
                int16_t number;
7398
                return get_number(number) and sax->number_integer(number);
7399
            }
7400
7401
            case 'l':
7402
            {
7403
                int32_t number;
7404
                return get_number(number) and sax->number_integer(number);
7405
            }
7406
7407
            case 'L':
7408
            {
7409
                int64_t number;
7410
                return get_number(number) and sax->number_integer(number);
7411
            }
7412
7413
            case 'd':
7414
            {
7415
                float number;
7416
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
7417
            }
7418
7419
            case 'D':
7420
            {
7421
                double number;
7422
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
7423
            }
7424
7425
            case 'C':  // char
7426
            {
7427
                get();
7428
                if (JSON_UNLIKELY(not unexpect_eof()))
7429
                {
7430
                    return false;
7431
                }
7432
                if (JSON_UNLIKELY(current > 127))
7433
                {
7434
                    auto last_token = get_token_string();
7435
                    return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token));
7436
                }
7437
                string_t s(1, static_cast<char>(current));
7438
                return sax->string(s);
7439
            }
7440
7441
            case 'S':  // string
7442
            {
7443
                string_t s;
7444
                return get_ubjson_string(s) and sax->string(s);
7445
            }
7446
7447
            case '[':  // array
7448
                return get_ubjson_array();
7449
7450
            case '{':  // object
7451
                return get_ubjson_object();
7452
7453
            default: // anything else
7454
            {
7455
                auto last_token = get_token_string();
7456
                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading UBJSON; last byte: 0x" + last_token));
7457
            }
7458
        }
7459
    }
7460
7461
    /*!
7462
    @return whether array creation completed
7463
    */
7464
    bool get_ubjson_array()
7465
    {
7466
        std::pair<std::size_t, int> size_and_type;
7467
        if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
7468
        {
7469
            return false;
7470
        }
7471
7472
        if (size_and_type.first != string_t::npos)
7473
        {
7474
            if (JSON_UNLIKELY(not sax->start_array(size_and_type.first)))
7475
            {
7476
                return false;
7477
            }
7478
7479
            if (size_and_type.second != 0)
7480
            {
7481
                if (size_and_type.second != 'N')
7482
                {
7483
                    for (std::size_t i = 0; i < size_and_type.first; ++i)
7484
                    {
7485
                        if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
7486
                        {
7487
                            return false;
7488
                        }
7489
                    }
7490
                }
7491
            }
7492
            else
7493
            {
7494
                for (std::size_t i = 0; i < size_and_type.first; ++i)
7495
                {
7496
                    if (JSON_UNLIKELY(not parse_ubjson_internal()))
7497
                    {
7498
                        return false;
7499
                    }
7500
                }
7501
            }
7502
        }
7503
        else
7504
        {
7505
            if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
7506
            {
7507
                return false;
7508
            }
7509
7510
            while (current != ']')
7511
            {
7512
                if (JSON_UNLIKELY(not parse_ubjson_internal(false)))
7513
                {
7514
                    return false;
7515
                }
7516
                get_ignore_noop();
7517
            }
7518
        }
7519
7520
        return sax->end_array();
7521
    }
7522
7523
    /*!
7524
    @return whether object creation completed
7525
    */
7526
    bool get_ubjson_object()
7527
    {
7528
        std::pair<std::size_t, int> size_and_type;
7529
        if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
7530
        {
7531
            return false;
7532
        }
7533
7534
        string_t key;
7535
        if (size_and_type.first != string_t::npos)
7536
        {
7537
            if (JSON_UNLIKELY(not sax->start_object(size_and_type.first)))
7538
            {
7539
                return false;
7540
            }
7541
7542
            if (size_and_type.second != 0)
7543
            {
7544
                for (std::size_t i = 0; i < size_and_type.first; ++i)
7545
                {
7546
                    if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
7547
                    {
7548
                        return false;
7549
                    }
7550
                    if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
7551
                    {
7552
                        return false;
7553
                    }
7554
                    key.clear();
7555
                }
7556
            }
7557
            else
7558
            {
7559
                for (std::size_t i = 0; i < size_and_type.first; ++i)
7560
                {
7561
                    if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
7562
                    {
7563
                        return false;
7564
                    }
7565
                    if (JSON_UNLIKELY(not parse_ubjson_internal()))
7566
                    {
7567
                        return false;
7568
                    }
7569
                    key.clear();
7570
                }
7571
            }
7572
        }
7573
        else
7574
        {
7575
            if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
7576
            {
7577
                return false;
7578
            }
7579
7580
            while (current != '}')
7581
            {
7582
                if (JSON_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key)))
7583
                {
7584
                    return false;
7585
                }
7586
                if (JSON_UNLIKELY(not parse_ubjson_internal()))
7587
                {
7588
                    return false;
7589
                }
7590
                get_ignore_noop();
7591
                key.clear();
7592
            }
7593
        }
7594
7595
        return sax->end_object();
7596
    }
7597
7598
    /*!
7599
    @return whether the last read character is not EOF
7600
    */
7601
    bool unexpect_eof() const
7602
    {
7603
        if (JSON_UNLIKELY(current == std::char_traits<char>::eof()))
7604
        {
7605
            return sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, "unexpected end of input"));
7606
        }
7607
        return true;
7608
    }
7609
7610
    /*!
7611
    @return a string representation of the last read byte
7612
    */
7613
    std::string get_token_string() const
7614
    {
7615
        char cr[3];
7616
        snprintf(cr, 3, "%.2hhX", static_cast<unsigned char>(current));
7617
        return std::string{cr};
7618
    }
7619
7620
  private:
7621
    /// input adapter
7622
    input_adapter_t ia = nullptr;
7623
7624
    /// the current character
7625
    int current = std::char_traits<char>::eof();
7626
7627
    /// the number of characters read
7628
    std::size_t chars_read = 0;
7629
7630
    /// whether we can assume little endianess
7631
    const bool is_little_endian = little_endianess();
7632
7633
    /// the SAX parser
7634
    json_sax_t* sax = nullptr;
7635
};
7636
}
7637
}
7638
7639
// #include <nlohmann/detail/output/binary_writer.hpp>
7640
7641
7642
#include <algorithm> // reverse
7643
#include <array> // array
7644
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
7645
#include <cstring> // memcpy
7646
#include <limits> // numeric_limits
7647
7648
// #include <nlohmann/detail/input/binary_reader.hpp>
7649
7650
// #include <nlohmann/detail/output/output_adapters.hpp>
7651
7652
7653
namespace nlohmann
7654
{
7655
namespace detail
7656
{
7657
///////////////////
7658
// binary writer //
7659
///////////////////
7660
7661
/*!
7662
@brief serialization to CBOR and MessagePack values
7663
*/
7664
template<typename BasicJsonType, typename CharType>
7665
class binary_writer
7666
{
7667
  public:
7668
    /*!
7669
    @brief create a binary writer
7670
7671
    @param[in] adapter  output adapter to write to
7672
    */
7673
    explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
7674
    {
7675
        assert(oa);
7676
    }
7677
7678
    /*!
7679
    @brief[in] j  JSON value to serialize
7680
    */
7681
    void write_cbor(const BasicJsonType& j)
7682
    {
7683
        switch (j.type())
7684
        {
7685
            case value_t::null:
7686
            {
7687
                oa->write_character(static_cast<CharType>(0xF6));
7688
                break;
7689
            }
7690
7691
            case value_t::boolean:
7692
            {
7693
                oa->write_character(j.m_value.boolean
7694
                                    ? static_cast<CharType>(0xF5)
7695
                                    : static_cast<CharType>(0xF4));
7696
                break;
7697
            }
7698
7699
            case value_t::number_integer:
7700
            {
7701
                if (j.m_value.number_integer >= 0)
7702
                {
7703
                    // CBOR does not differentiate between positive signed
7704
                    // integers and unsigned integers. Therefore, we used the
7705
                    // code from the value_t::number_unsigned case here.
7706
                    if (j.m_value.number_integer <= 0x17)
7707
                    {
7708
                        write_number(static_cast<uint8_t>(j.m_value.number_integer));
7709
                    }
7710
                    else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
7711
                    {
7712
                        oa->write_character(static_cast<CharType>(0x18));
7713
                        write_number(static_cast<uint8_t>(j.m_value.number_integer));
7714
                    }
7715
                    else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())
7716
                    {
7717
                        oa->write_character(static_cast<CharType>(0x19));
7718
                        write_number(static_cast<uint16_t>(j.m_value.number_integer));
7719
                    }
7720
                    else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())
7721
                    {
7722
                        oa->write_character(static_cast<CharType>(0x1A));
7723
                        write_number(static_cast<uint32_t>(j.m_value.number_integer));
7724
                    }
7725
                    else
7726
                    {
7727
                        oa->write_character(static_cast<CharType>(0x1B));
7728
                        write_number(static_cast<uint64_t>(j.m_value.number_integer));
7729
                    }
7730
                }
7731
                else
7732
                {
7733
                    // The conversions below encode the sign in the first
7734
                    // byte, and the value is converted to a positive number.
7735
                    const auto positive_number = -1 - j.m_value.number_integer;
7736
                    if (j.m_value.number_integer >= -24)
7737
                    {
7738
                        write_number(static_cast<uint8_t>(0x20 + positive_number));
7739
                    }
7740
                    else if (positive_number <= (std::numeric_limits<uint8_t>::max)())
7741
                    {
7742
                        oa->write_character(static_cast<CharType>(0x38));
7743
                        write_number(static_cast<uint8_t>(positive_number));
7744
                    }
7745
                    else if (positive_number <= (std::numeric_limits<uint16_t>::max)())
7746
                    {
7747
                        oa->write_character(static_cast<CharType>(0x39));
7748
                        write_number(static_cast<uint16_t>(positive_number));
7749
                    }
7750
                    else if (positive_number <= (std::numeric_limits<uint32_t>::max)())
7751
                    {
7752
                        oa->write_character(static_cast<CharType>(0x3A));
7753
                        write_number(static_cast<uint32_t>(positive_number));
7754
                    }
7755
                    else
7756
                    {
7757
                        oa->write_character(static_cast<CharType>(0x3B));
7758
                        write_number(static_cast<uint64_t>(positive_number));
7759
                    }
7760
                }
7761
                break;
7762
            }
7763
7764
            case value_t::number_unsigned:
7765
            {
7766
                if (j.m_value.number_unsigned <= 0x17)
7767
                {
7768
                    write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
7769
                }
7770
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
7771
                {
7772
                    oa->write_character(static_cast<CharType>(0x18));
7773
                    write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
7774
                }
7775
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
7776
                {
7777
                    oa->write_character(static_cast<CharType>(0x19));
7778
                    write_number(static_cast<uint16_t>(j.m_value.number_unsigned));
7779
                }
7780
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
7781
                {
7782
                    oa->write_character(static_cast<CharType>(0x1A));
7783
                    write_number(static_cast<uint32_t>(j.m_value.number_unsigned));
7784
                }
7785
                else
7786
                {
7787
                    oa->write_character(static_cast<CharType>(0x1B));
7788
                    write_number(static_cast<uint64_t>(j.m_value.number_unsigned));
7789
                }
7790
                break;
7791
            }
7792
7793
            case value_t::number_float:
7794
            {
7795
                oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
7796
                write_number(j.m_value.number_float);
7797
                break;
7798
            }
7799
7800
            case value_t::string:
7801
            {
7802
                // step 1: write control byte and the string length
7803
                const auto N = j.m_value.string->size();
7804
                if (N <= 0x17)
7805
                {
7806
                    write_number(static_cast<uint8_t>(0x60 + N));
7807
                }
7808
                else if (N <= (std::numeric_limits<uint8_t>::max)())
7809
                {
7810
                    oa->write_character(static_cast<CharType>(0x78));
7811
                    write_number(static_cast<uint8_t>(N));
7812
                }
7813
                else if (N <= (std::numeric_limits<uint16_t>::max)())
7814
                {
7815
                    oa->write_character(static_cast<CharType>(0x79));
7816
                    write_number(static_cast<uint16_t>(N));
7817
                }
7818
                else if (N <= (std::numeric_limits<uint32_t>::max)())
7819
                {
7820
                    oa->write_character(static_cast<CharType>(0x7A));
7821
                    write_number(static_cast<uint32_t>(N));
7822
                }
7823
                // LCOV_EXCL_START
7824
                else if (N <= (std::numeric_limits<uint64_t>::max)())
7825
                {
7826
                    oa->write_character(static_cast<CharType>(0x7B));
7827
                    write_number(static_cast<uint64_t>(N));
7828
                }
7829
                // LCOV_EXCL_STOP
7830
7831
                // step 2: write the string
7832
                oa->write_characters(
7833
                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
7834
                    j.m_value.string->size());
7835
                break;
7836
            }
7837
7838
            case value_t::array:
7839
            {
7840
                // step 1: write control byte and the array size
7841
                const auto N = j.m_value.array->size();
7842
                if (N <= 0x17)
7843
                {
7844
                    write_number(static_cast<uint8_t>(0x80 + N));
7845
                }
7846
                else if (N <= (std::numeric_limits<uint8_t>::max)())
7847
                {
7848
                    oa->write_character(static_cast<CharType>(0x98));
7849
                    write_number(static_cast<uint8_t>(N));
7850
                }
7851
                else if (N <= (std::numeric_limits<uint16_t>::max)())
7852
                {
7853
                    oa->write_character(static_cast<CharType>(0x99));
7854
                    write_number(static_cast<uint16_t>(N));
7855
                }
7856
                else if (N <= (std::numeric_limits<uint32_t>::max)())
7857
                {
7858
                    oa->write_character(static_cast<CharType>(0x9A));
7859
                    write_number(static_cast<uint32_t>(N));
7860
                }
7861
                // LCOV_EXCL_START
7862
                else if (N <= (std::numeric_limits<uint64_t>::max)())
7863
                {
7864
                    oa->write_character(static_cast<CharType>(0x9B));
7865
                    write_number(static_cast<uint64_t>(N));
7866
                }
7867
                // LCOV_EXCL_STOP
7868
7869
                // step 2: write each element
7870
                for (const auto& el : *j.m_value.array)
7871
                {
7872
                    write_cbor(el);
7873
                }
7874
                break;
7875
            }
7876
7877
            case value_t::object:
7878
            {
7879
                // step 1: write control byte and the object size
7880
                const auto N = j.m_value.object->size();
7881
                if (N <= 0x17)
7882
                {
7883
                    write_number(static_cast<uint8_t>(0xA0 + N));
7884
                }
7885
                else if (N <= (std::numeric_limits<uint8_t>::max)())
7886
                {
7887
                    oa->write_character(static_cast<CharType>(0xB8));
7888
                    write_number(static_cast<uint8_t>(N));
7889
                }
7890
                else if (N <= (std::numeric_limits<uint16_t>::max)())
7891
                {
7892
                    oa->write_character(static_cast<CharType>(0xB9));
7893
                    write_number(static_cast<uint16_t>(N));
7894
                }
7895
                else if (N <= (std::numeric_limits<uint32_t>::max)())
7896
                {
7897
                    oa->write_character(static_cast<CharType>(0xBA));
7898
                    write_number(static_cast<uint32_t>(N));
7899
                }
7900
                // LCOV_EXCL_START
7901
                else if (N <= (std::numeric_limits<uint64_t>::max)())
7902
                {
7903
                    oa->write_character(static_cast<CharType>(0xBB));
7904
                    write_number(static_cast<uint64_t>(N));
7905
                }
7906
                // LCOV_EXCL_STOP
7907
7908
                // step 2: write each element
7909
                for (const auto& el : *j.m_value.object)
7910
                {
7911
                    write_cbor(el.first);
7912
                    write_cbor(el.second);
7913
                }
7914
                break;
7915
            }
7916
7917
            default:
7918
                break;
7919
        }
7920
    }
7921
7922
    /*!
7923
    @brief[in] j  JSON value to serialize
7924
    */
7925
    void write_msgpack(const BasicJsonType& j)
7926
    {
7927
        switch (j.type())
7928
        {
7929
            case value_t::null: // nil
7930
            {
7931
                oa->write_character(static_cast<CharType>(0xC0));
7932
                break;
7933
            }
7934
7935
            case value_t::boolean: // true and false
7936
            {
7937
                oa->write_character(j.m_value.boolean
7938
                                    ? static_cast<CharType>(0xC3)
7939
                                    : static_cast<CharType>(0xC2));
7940
                break;
7941
            }
7942
7943
            case value_t::number_integer:
7944
            {
7945
                if (j.m_value.number_integer >= 0)
7946
                {
7947
                    // MessagePack does not differentiate between positive
7948
                    // signed integers and unsigned integers. Therefore, we used
7949
                    // the code from the value_t::number_unsigned case here.
7950
                    if (j.m_value.number_unsigned < 128)
7951
                    {
7952
                        // positive fixnum
7953
                        write_number(static_cast<uint8_t>(j.m_value.number_integer));
7954
                    }
7955
                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
7956
                    {
7957
                        // uint 8
7958
                        oa->write_character(static_cast<CharType>(0xCC));
7959
                        write_number(static_cast<uint8_t>(j.m_value.number_integer));
7960
                    }
7961
                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
7962
                    {
7963
                        // uint 16
7964
                        oa->write_character(static_cast<CharType>(0xCD));
7965
                        write_number(static_cast<uint16_t>(j.m_value.number_integer));
7966
                    }
7967
                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
7968
                    {
7969
                        // uint 32
7970
                        oa->write_character(static_cast<CharType>(0xCE));
7971
                        write_number(static_cast<uint32_t>(j.m_value.number_integer));
7972
                    }
7973
                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
7974
                    {
7975
                        // uint 64
7976
                        oa->write_character(static_cast<CharType>(0xCF));
7977
                        write_number(static_cast<uint64_t>(j.m_value.number_integer));
7978
                    }
7979
                }
7980
                else
7981
                {
7982
                    if (j.m_value.number_integer >= -32)
7983
                    {
7984
                        // negative fixnum
7985
                        write_number(static_cast<int8_t>(j.m_value.number_integer));
7986
                    }
7987
                    else if (j.m_value.number_integer >= (std::numeric_limits<int8_t>::min)() and
7988
                             j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
7989
                    {
7990
                        // int 8
7991
                        oa->write_character(static_cast<CharType>(0xD0));
7992
                        write_number(static_cast<int8_t>(j.m_value.number_integer));
7993
                    }
7994
                    else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and
7995
                             j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
7996
                    {
7997
                        // int 16
7998
                        oa->write_character(static_cast<CharType>(0xD1));
7999
                        write_number(static_cast<int16_t>(j.m_value.number_integer));
8000
                    }
8001
                    else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and
8002
                             j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
8003
                    {
8004
                        // int 32
8005
                        oa->write_character(static_cast<CharType>(0xD2));
8006
                        write_number(static_cast<int32_t>(j.m_value.number_integer));
8007
                    }
8008
                    else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and
8009
                             j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())
8010
                    {
8011
                        // int 64
8012
                        oa->write_character(static_cast<CharType>(0xD3));
8013
                        write_number(static_cast<int64_t>(j.m_value.number_integer));
8014
                    }
8015
                }
8016
                break;
8017
            }
8018
8019
            case value_t::number_unsigned:
8020
            {
8021
                if (j.m_value.number_unsigned < 128)
8022
                {
8023
                    // positive fixnum
8024
                    write_number(static_cast<uint8_t>(j.m_value.number_integer));
8025
                }
8026
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
8027
                {
8028
                    // uint 8
8029
                    oa->write_character(static_cast<CharType>(0xCC));
8030
                    write_number(static_cast<uint8_t>(j.m_value.number_integer));
8031
                }
8032
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
8033
                {
8034
                    // uint 16
8035
                    oa->write_character(static_cast<CharType>(0xCD));
8036
                    write_number(static_cast<uint16_t>(j.m_value.number_integer));
8037
                }
8038
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
8039
                {
8040
                    // uint 32
8041
                    oa->write_character(static_cast<CharType>(0xCE));
8042
                    write_number(static_cast<uint32_t>(j.m_value.number_integer));
8043
                }
8044
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
8045
                {
8046
                    // uint 64
8047
                    oa->write_character(static_cast<CharType>(0xCF));
8048
                    write_number(static_cast<uint64_t>(j.m_value.number_integer));
8049
                }
8050
                break;
8051
            }
8052
8053
            case value_t::number_float:
8054
            {
8055
                oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
8056
                write_number(j.m_value.number_float);
8057
                break;
8058
            }
8059
8060
            case value_t::string:
8061
            {
8062
                // step 1: write control byte and the string length
8063
                const auto N = j.m_value.string->size();
8064
                if (N <= 31)
8065
                {
8066
                    // fixstr
8067
                    write_number(static_cast<uint8_t>(0xA0 | N));
8068
                }
8069
                else if (N <= (std::numeric_limits<uint8_t>::max)())
8070
                {
8071
                    // str 8
8072
                    oa->write_character(static_cast<CharType>(0xD9));
8073
                    write_number(static_cast<uint8_t>(N));
8074
                }
8075
                else if (N <= (std::numeric_limits<uint16_t>::max)())
8076
                {
8077
                    // str 16
8078
                    oa->write_character(static_cast<CharType>(0xDA));
8079
                    write_number(static_cast<uint16_t>(N));
8080
                }
8081
                else if (N <= (std::numeric_limits<uint32_t>::max)())
8082
                {
8083
                    // str 32
8084
                    oa->write_character(static_cast<CharType>(0xDB));
8085
                    write_number(static_cast<uint32_t>(N));
8086
                }
8087
8088
                // step 2: write the string
8089
                oa->write_characters(
8090
                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
8091
                    j.m_value.string->size());
8092
                break;
8093
            }
8094
8095
            case value_t::array:
8096
            {
8097
                // step 1: write control byte and the array size
8098
                const auto N = j.m_value.array->size();
8099
                if (N <= 15)
8100
                {
8101
                    // fixarray
8102
                    write_number(static_cast<uint8_t>(0x90 | N));
8103
                }
8104
                else if (N <= (std::numeric_limits<uint16_t>::max)())
8105
                {
8106
                    // array 16
8107
                    oa->write_character(static_cast<CharType>(0xDC));
8108
                    write_number(static_cast<uint16_t>(N));
8109
                }
8110
                else if (N <= (std::numeric_limits<uint32_t>::max)())
8111
                {
8112
                    // array 32
8113
                    oa->write_character(static_cast<CharType>(0xDD));
8114
                    write_number(static_cast<uint32_t>(N));
8115
                }
8116
8117
                // step 2: write each element
8118
                for (const auto& el : *j.m_value.array)
8119
                {
8120
                    write_msgpack(el);
8121
                }
8122
                break;
8123
            }
8124
8125
            case value_t::object:
8126
            {
8127
                // step 1: write control byte and the object size
8128
                const auto N = j.m_value.object->size();
8129
                if (N <= 15)
8130
                {
8131
                    // fixmap
8132
                    write_number(static_cast<uint8_t>(0x80 | (N & 0xF)));
8133
                }
8134
                else if (N <= (std::numeric_limits<uint16_t>::max)())
8135
                {
8136
                    // map 16
8137
                    oa->write_character(static_cast<CharType>(0xDE));
8138
                    write_number(static_cast<uint16_t>(N));
8139
                }
8140
                else if (N <= (std::numeric_limits<uint32_t>::max)())
8141
                {
8142
                    // map 32
8143
                    oa->write_character(static_cast<CharType>(0xDF));
8144
                    write_number(static_cast<uint32_t>(N));
8145
                }
8146
8147
                // step 2: write each element
8148
                for (const auto& el : *j.m_value.object)
8149
                {
8150
                    write_msgpack(el.first);
8151
                    write_msgpack(el.second);
8152
                }
8153
                break;
8154
            }
8155
8156
            default:
8157
                break;
8158
        }
8159
    }
8160
8161
    /*!
8162
    @param[in] j  JSON value to serialize
8163
    @param[in] use_count   whether to use '#' prefixes (optimized format)
8164
    @param[in] use_type    whether to use '$' prefixes (optimized format)
8165
    @param[in] add_prefix  whether prefixes need to be used for this value
8166
    */
8167
    void write_ubjson(const BasicJsonType& j, const bool use_count,
8168
                      const bool use_type, const bool add_prefix = true)
8169
    {
8170
        switch (j.type())
8171
        {
8172
            case value_t::null:
8173
            {
8174
                if (add_prefix)
8175
                {
8176
                    oa->write_character(static_cast<CharType>('Z'));
8177
                }
8178
                break;
8179
            }
8180
8181
            case value_t::boolean:
8182
            {
8183
                if (add_prefix)
8184
                    oa->write_character(j.m_value.boolean
8185
                                        ? static_cast<CharType>('T')
8186
                                        : static_cast<CharType>('F'));
8187
                break;
8188
            }
8189
8190
            case value_t::number_integer:
8191
            {
8192
                write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
8193
                break;
8194
            }
8195
8196
            case value_t::number_unsigned:
8197
            {
8198
                write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
8199
                break;
8200
            }
8201
8202
            case value_t::number_float:
8203
            {
8204
                write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
8205
                break;
8206
            }
8207
8208
            case value_t::string:
8209
            {
8210
                if (add_prefix)
8211
                {
8212
                    oa->write_character(static_cast<CharType>('S'));
8213
                }
8214
                write_number_with_ubjson_prefix(j.m_value.string->size(), true);
8215
                oa->write_characters(
8216
                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
8217
                    j.m_value.string->size());
8218
                break;
8219
            }
8220
8221
            case value_t::array:
8222
            {
8223
                if (add_prefix)
8224
                {
8225
                    oa->write_character(static_cast<CharType>('['));
8226
                }
8227
8228
                bool prefix_required = true;
8229
                if (use_type and not j.m_value.array->empty())
8230
                {
8231
                    assert(use_count);
8232
                    const CharType first_prefix = ubjson_prefix(j.front());
8233
                    const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
8234
                                                         [this, first_prefix](const BasicJsonType & v)
8235
                    {
8236
                        return ubjson_prefix(v) == first_prefix;
8237
                    });
8238
8239
                    if (same_prefix)
8240
                    {
8241
                        prefix_required = false;
8242
                        oa->write_character(static_cast<CharType>('$'));
8243
                        oa->write_character(first_prefix);
8244
                    }
8245
                }
8246
8247
                if (use_count)
8248
                {
8249
                    oa->write_character(static_cast<CharType>('#'));
8250
                    write_number_with_ubjson_prefix(j.m_value.array->size(), true);
8251
                }
8252
8253
                for (const auto& el : *j.m_value.array)
8254
                {
8255
                    write_ubjson(el, use_count, use_type, prefix_required);
8256
                }
8257
8258
                if (not use_count)
8259
                {
8260
                    oa->write_character(static_cast<CharType>(']'));
8261
                }
8262
8263
                break;
8264
            }
8265
8266
            case value_t::object:
8267
            {
8268
                if (add_prefix)
8269
                {
8270
                    oa->write_character(static_cast<CharType>('{'));
8271
                }
8272
8273
                bool prefix_required = true;
8274
                if (use_type and not j.m_value.object->empty())
8275
                {
8276
                    assert(use_count);
8277
                    const CharType first_prefix = ubjson_prefix(j.front());
8278
                    const bool same_prefix = std::all_of(j.begin(), j.end(),
8279
                                                         [this, first_prefix](const BasicJsonType & v)
8280
                    {
8281
                        return ubjson_prefix(v) == first_prefix;
8282
                    });
8283
8284
                    if (same_prefix)
8285
                    {
8286
                        prefix_required = false;
8287
                        oa->write_character(static_cast<CharType>('$'));
8288
                        oa->write_character(first_prefix);
8289
                    }
8290
                }
8291
8292
                if (use_count)
8293
                {
8294
                    oa->write_character(static_cast<CharType>('#'));
8295
                    write_number_with_ubjson_prefix(j.m_value.object->size(), true);
8296
                }
8297
8298
                for (const auto& el : *j.m_value.object)
8299
                {
8300
                    write_number_with_ubjson_prefix(el.first.size(), true);
8301
                    oa->write_characters(
8302
                        reinterpret_cast<const CharType*>(el.first.c_str()),
8303
                        el.first.size());
8304
                    write_ubjson(el.second, use_count, use_type, prefix_required);
8305
                }
8306
8307
                if (not use_count)
8308
                {
8309
                    oa->write_character(static_cast<CharType>('}'));
8310
                }
8311
8312
                break;
8313
            }
8314
8315
            default:
8316
                break;
8317
        }
8318
    }
8319
8320
  private:
8321
    /*
8322
    @brief write a number to output input
8323
8324
    @param[in] n number of type @a NumberType
8325
    @tparam NumberType the type of the number
8326
8327
    @note This function needs to respect the system's endianess, because bytes
8328
          in CBOR, MessagePack, and UBJSON are stored in network order (big
8329
          endian) and therefore need reordering on little endian systems.
8330
    */
8331
    template<typename NumberType>
8332
    void write_number(const NumberType n)
8333
    {
8334
        // step 1: write number to array of length NumberType
8335
        std::array<CharType, sizeof(NumberType)> vec;
8336
        std::memcpy(vec.data(), &n, sizeof(NumberType));
8337
8338
        // step 2: write array to output (with possible reordering)
8339
        if (is_little_endian)
8340
        {
8341
            // reverse byte order prior to conversion if necessary
8342
            std::reverse(vec.begin(), vec.end());
8343
        }
8344
8345
        oa->write_characters(vec.data(), sizeof(NumberType));
8346
    }
8347
8348
    // UBJSON: write number (floating point)
8349
    template<typename NumberType, typename std::enable_if<
8350
                 std::is_floating_point<NumberType>::value, int>::type = 0>
8351
    void write_number_with_ubjson_prefix(const NumberType n,
8352
                                         const bool add_prefix)
8353
    {
8354
        if (add_prefix)
8355
        {
8356
            oa->write_character(get_ubjson_float_prefix(n));
8357
        }
8358
        write_number(n);
8359
    }
8360
8361
    // UBJSON: write number (unsigned integer)
8362
    template<typename NumberType, typename std::enable_if<
8363
                 std::is_unsigned<NumberType>::value, int>::type = 0>
8364
    void write_number_with_ubjson_prefix(const NumberType n,
8365
                                         const bool add_prefix)
8366
    {
8367
        if (n <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))
8368
        {
8369
            if (add_prefix)
8370
            {
8371
                oa->write_character(static_cast<CharType>('i'));  // int8
8372
            }
8373
            write_number(static_cast<uint8_t>(n));
8374
        }
8375
        else if (n <= (std::numeric_limits<uint8_t>::max)())
8376
        {
8377
            if (add_prefix)
8378
            {
8379
                oa->write_character(static_cast<CharType>('U'));  // uint8
8380
            }
8381
            write_number(static_cast<uint8_t>(n));
8382
        }
8383
        else if (n <= static_cast<uint64_t>((std::numeric_limits<int16_t>::max)()))
8384
        {
8385
            if (add_prefix)
8386
            {
8387
                oa->write_character(static_cast<CharType>('I'));  // int16
8388
            }
8389
            write_number(static_cast<int16_t>(n));
8390
        }
8391
        else if (n <= static_cast<uint64_t>((std::numeric_limits<int32_t>::max)()))
8392
        {
8393
            if (add_prefix)
8394
            {
8395
                oa->write_character(static_cast<CharType>('l'));  // int32
8396
            }
8397
            write_number(static_cast<int32_t>(n));
8398
        }
8399
        else if (n <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()))
8400
        {
8401
            if (add_prefix)
8402
            {
8403
                oa->write_character(static_cast<CharType>('L'));  // int64
8404
            }
8405
            write_number(static_cast<int64_t>(n));
8406
        }
8407
        else
8408
        {
8409
            JSON_THROW(out_of_range::create(407, "number overflow serializing " + std::to_string(n)));
8410
        }
8411
    }
8412
8413
    // UBJSON: write number (signed integer)
8414
    template<typename NumberType, typename std::enable_if<
8415
                 std::is_signed<NumberType>::value and
8416
                 not std::is_floating_point<NumberType>::value, int>::type = 0>
8417
    void write_number_with_ubjson_prefix(const NumberType n,
8418
                                         const bool add_prefix)
8419
    {
8420
        if ((std::numeric_limits<int8_t>::min)() <= n and n <= (std::numeric_limits<int8_t>::max)())
8421
        {
8422
            if (add_prefix)
8423
            {
8424
                oa->write_character(static_cast<CharType>('i'));  // int8
8425
            }
8426
            write_number(static_cast<int8_t>(n));
8427
        }
8428
        else if (static_cast<int64_t>((std::numeric_limits<uint8_t>::min)()) <= n and n <= static_cast<int64_t>((std::numeric_limits<uint8_t>::max)()))
8429
        {
8430
            if (add_prefix)
8431
            {
8432
                oa->write_character(static_cast<CharType>('U'));  // uint8
8433
            }
8434
            write_number(static_cast<uint8_t>(n));
8435
        }
8436
        else if ((std::numeric_limits<int16_t>::min)() <= n and n <= (std::numeric_limits<int16_t>::max)())
8437
        {
8438
            if (add_prefix)
8439
            {
8440
                oa->write_character(static_cast<CharType>('I'));  // int16
8441
            }
8442
            write_number(static_cast<int16_t>(n));
8443
        }
8444
        else if ((std::numeric_limits<int32_t>::min)() <= n and n <= (std::numeric_limits<int32_t>::max)())
8445
        {
8446
            if (add_prefix)
8447
            {
8448
                oa->write_character(static_cast<CharType>('l'));  // int32
8449
            }
8450
            write_number(static_cast<int32_t>(n));
8451
        }
8452
        else if ((std::numeric_limits<int64_t>::min)() <= n and n <= (std::numeric_limits<int64_t>::max)())
8453
        {
8454
            if (add_prefix)
8455
            {
8456
                oa->write_character(static_cast<CharType>('L'));  // int64
8457
            }
8458
            write_number(static_cast<int64_t>(n));
8459
        }
8460
        // LCOV_EXCL_START
8461
        else
8462
        {
8463
            JSON_THROW(out_of_range::create(407, "number overflow serializing " + std::to_string(n)));
8464
        }
8465
        // LCOV_EXCL_STOP
8466
    }
8467
8468
    /*!
8469
    @brief determine the type prefix of container values
8470
8471
    @note This function does not need to be 100% accurate when it comes to
8472
          integer limits. In case a number exceeds the limits of int64_t,
8473
          this will be detected by a later call to function
8474
          write_number_with_ubjson_prefix. Therefore, we return 'L' for any
8475
          value that does not fit the previous limits.
8476
    */
8477
    CharType ubjson_prefix(const BasicJsonType& j) const noexcept
8478
    {
8479
        switch (j.type())
8480
        {
8481
            case value_t::null:
8482
                return 'Z';
8483
8484
            case value_t::boolean:
8485
                return j.m_value.boolean ? 'T' : 'F';
8486
8487
            case value_t::number_integer:
8488
            {
8489
                if ((std::numeric_limits<int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
8490
                {
8491
                    return 'i';
8492
                }
8493
                else if ((std::numeric_limits<uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
8494
                {
8495
                    return 'U';
8496
                }
8497
                else if ((std::numeric_limits<int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
8498
                {
8499
                    return 'I';
8500
                }
8501
                else if ((std::numeric_limits<int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
8502
                {
8503
                    return 'l';
8504
                }
8505
                else  // no check and assume int64_t (see note above)
8506
                {
8507
                    return 'L';
8508
                }
8509
            }
8510
8511
            case value_t::number_unsigned:
8512
            {
8513
                if (j.m_value.number_unsigned <= (std::numeric_limits<int8_t>::max)())
8514
                {
8515
                    return 'i';
8516
                }
8517
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
8518
                {
8519
                    return 'U';
8520
                }
8521
                else if (j.m_value.number_unsigned <= (std::numeric_limits<int16_t>::max)())
8522
                {
8523
                    return 'I';
8524
                }
8525
                else if (j.m_value.number_unsigned <= (std::numeric_limits<int32_t>::max)())
8526
                {
8527
                    return 'l';
8528
                }
8529
                else  // no check and assume int64_t (see note above)
8530
                {
8531
                    return 'L';
8532
                }
8533
            }
8534
8535
            case value_t::number_float:
8536
                return get_ubjson_float_prefix(j.m_value.number_float);
8537
8538
            case value_t::string:
8539
                return 'S';
8540
8541
            case value_t::array:
8542
                return '[';
8543
8544
            case value_t::object:
8545
                return '{';
8546
8547
            default:  // discarded values
8548
                return 'N';
8549
        }
8550
    }
8551
8552
    static constexpr CharType get_cbor_float_prefix(float)
8553
    {
8554
        return static_cast<CharType>(0xFA);  // Single-Precision Float
8555
    }
8556
8557
    static constexpr CharType get_cbor_float_prefix(double)
8558
    {
8559
        return static_cast<CharType>(0xFB);  // Double-Precision Float
8560
    }
8561
8562
    static constexpr CharType get_msgpack_float_prefix(float)
8563
    {
8564
        return static_cast<CharType>(0xCA);  // float 32
8565
    }
8566
8567
    static constexpr CharType get_msgpack_float_prefix(double)
8568
    {
8569
        return static_cast<CharType>(0xCB);  // float 64
8570
    }
8571
8572
    static constexpr CharType get_ubjson_float_prefix(float)
8573
    {
8574
        return 'd';  // float 32
8575
    }
8576
8577
    static constexpr CharType get_ubjson_float_prefix(double)
8578
    {
8579
        return 'D';  // float 64
8580
    }
8581
8582
  private:
8583
    /// whether we can assume little endianess
8584
    const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
8585
8586
    /// the output
8587
    output_adapter_t<CharType> oa = nullptr;
8588
};
8589
}
8590
}
8591
8592
// #include <nlohmann/detail/output/serializer.hpp>
8593
8594
8595
#include <algorithm> // reverse, remove, fill, find, none_of
8596
#include <array> // array
8597
#include <cassert> // assert
8598
#include <ciso646> // and, or
8599
#include <clocale> // localeconv, lconv
8600
#include <cmath> // labs, isfinite, isnan, signbit
8601
#include <cstddef> // size_t, ptrdiff_t
8602
#include <cstdint> // uint8_t
8603
#include <cstdio> // snprintf
8604
#include <limits> // numeric_limits
8605
#include <string> // string
8606
#include <type_traits> // is_same
8607
8608
// #include <nlohmann/detail/exceptions.hpp>
8609
8610
// #include <nlohmann/detail/conversions/to_chars.hpp>
8611
8612
8613
#include <cassert> // assert
8614
#include <ciso646> // or, and, not
8615
#include <cmath>   // signbit, isfinite
8616
#include <cstdint> // intN_t, uintN_t
8617
#include <cstring> // memcpy, memmove
8618
8619
namespace nlohmann
8620
{
8621
namespace detail
8622
{
8623
8624
/*!
8625
@brief implements the Grisu2 algorithm for binary to decimal floating-point
8626
conversion.
8627
8628
This implementation is a slightly modified version of the reference
8629
implementation which may be obtained from
8630
http://florian.loitsch.com/publications (bench.tar.gz).
8631
8632
The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
8633
8634
For a detailed description of the algorithm see:
8635
8636
[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
8637
    Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
8638
    Language Design and Implementation, PLDI 2010
8639
[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
8640
    Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
8641
    Design and Implementation, PLDI 1996
8642
*/
8643
namespace dtoa_impl
8644
{
8645
8646
template <typename Target, typename Source>
8647
Target reinterpret_bits(const Source source)
28
8648
{
28
8649
    static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
28
8650
28
8651
    Target target;
28
8652
    std::memcpy(&target, &source, sizeof(Source));
28
8653
    return target;
28
8654
}
8655
8656
struct diyfp // f * 2^e
8657
{
8658
    static constexpr int kPrecision = 64; // = q
8659
8660
    uint64_t f;
8661
    int e;
8662
0
8663
    constexpr diyfp() noexcept : f(0), e(0) {}
364
8664
    constexpr diyfp(uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
8665
8666
    /*!
8667
    @brief returns x - y
8668
    @pre x.e == y.e and x.f >= y.f
8669
    */
8670
    static diyfp sub(const diyfp& x, const diyfp& y) noexcept
56
8671
    {
56
8672
        assert(x.e == y.e);
56
8673
        assert(x.f >= y.f);
56
8674
56
8675
        return diyfp(x.f - y.f, x.e);
56
8676
    }
8677
8678
    /*!
8679
    @brief returns x * y
8680
    @note The result is rounded. (Only the upper q bits are returned.)
8681
    */
8682
    static diyfp mul(const diyfp& x, const diyfp& y) noexcept
84
8683
    {
84
8684
        static_assert(kPrecision == 64, "internal error");
84
8685
84
8686
        // Computes:
84
8687
        //  f = round((x.f * y.f) / 2^q)
84
8688
        //  e = x.e + y.e + q
84
8689
84
8690
        // Emulate the 64-bit * 64-bit multiplication:
84
8691
        //
84
8692
        // p = u * v
84
8693
        //   = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
84
8694
        //   = (u_lo v_lo         ) + 2^32 ((u_lo v_hi         ) + (u_hi v_lo         )) + 2^64 (u_hi v_hi         )
84
8695
        //   = (p0                ) + 2^32 ((p1                ) + (p2                )) + 2^64 (p3                )
84
8696
        //   = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3                )
84
8697
        //   = (p0_lo             ) + 2^32 (p0_hi + p1_lo + p2_lo                      ) + 2^64 (p1_hi + p2_hi + p3)
84
8698
        //   = (p0_lo             ) + 2^32 (Q                                          ) + 2^64 (H                 )
84
8699
        //   = (p0_lo             ) + 2^32 (Q_lo + 2^32 Q_hi                           ) + 2^64 (H                 )
84
8700
        //
84
8701
        // (Since Q might be larger than 2^32 - 1)
84
8702
        //
84
8703
        //   = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
84
8704
        //
84
8705
        // (Q_hi + H does not overflow a 64-bit int)
84
8706
        //
84
8707
        //   = p_lo + 2^64 p_hi
84
8708
84
8709
        const uint64_t u_lo = x.f & 0xFFFFFFFF;
84
8710
        const uint64_t u_hi = x.f >> 32;
84
8711
        const uint64_t v_lo = y.f & 0xFFFFFFFF;
84
8712
        const uint64_t v_hi = y.f >> 32;
84
8713
84
8714
        const uint64_t p0 = u_lo * v_lo;
84
8715
        const uint64_t p1 = u_lo * v_hi;
84
8716
        const uint64_t p2 = u_hi * v_lo;
84
8717
        const uint64_t p3 = u_hi * v_hi;
84
8718
84
8719
        const uint64_t p0_hi = p0 >> 32;
84
8720
        const uint64_t p1_lo = p1 & 0xFFFFFFFF;
84
8721
        const uint64_t p1_hi = p1 >> 32;
84
8722
        const uint64_t p2_lo = p2 & 0xFFFFFFFF;
84
8723
        const uint64_t p2_hi = p2 >> 32;
84
8724
84
8725
        uint64_t Q = p0_hi + p1_lo + p2_lo;
84
8726
84
8727
        // The full product might now be computed as
84
8728
        //
84
8729
        // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
84
8730
        // p_lo = p0_lo + (Q << 32)
84
8731
        //
84
8732
        // But in this particular case here, the full p_lo is not required.
84
8733
        // Effectively we only need to add the highest bit in p_lo to p_hi (and
84
8734
        // Q_hi + 1 does not overflow).
84
8735
84
8736
        Q += uint64_t{1} << (64 - 32 - 1); // round, ties up
84
8737
84
8738
        const uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32);
84
8739
84
8740
        return diyfp(h, x.e + y.e + 64);
84
8741
    }
8742
8743
    /*!
8744
    @brief normalize x such that the significand is >= 2^(q-1)
8745
    @pre x.f != 0
8746
    */
8747
    static diyfp normalize(diyfp x) noexcept
56
8748
    {
56
8749
        assert(x.f != 0);
56
8750
644
8751
        while ((x.f >> 63) == 0)
588
8752
        {
588
8753
            x.f <<= 1;
588
8754
            x.e--;
588
8755
        }
56
8756
56
8757
        return x;
56
8758
    }
8759
8760
    /*!
8761
    @brief normalize x such that the result has the exponent E
8762
    @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
8763
    */
8764
    static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
28
8765
    {
28
8766
        const int delta = x.e - target_exponent;
28
8767
28
8768
        assert(delta >= 0);
28
8769
        assert(((x.f << delta) >> delta) == x.f);
28
8770
28
8771
        return diyfp(x.f << delta, target_exponent);
28
8772
    }
8773
};
8774
8775
struct boundaries
8776
{
8777
    diyfp w;
8778
    diyfp minus;
8779
    diyfp plus;
8780
};
8781
8782
/*!
8783
Compute the (normalized) diyfp representing the input number 'value' and its
8784
boundaries.
8785
8786
@pre value must be finite and positive
8787
*/
8788
template <typename FloatType>
8789
boundaries compute_boundaries(FloatType value)
28
8790
{
28
8791
    assert(std::isfinite(value));
28
8792
    assert(value > 0);
28
8793
28
8794
    // Convert the IEEE representation into a diyfp.
28
8795
    //
28
8796
    // If v is denormal:
28
8797
    //      value = 0.F * 2^(1 - bias) = (          F) * 2^(1 - bias - (p-1))
28
8798
    // If v is normalized:
28
8799
    //      value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
28
8800
28
8801
    static_assert(std::numeric_limits<FloatType>::is_iec559,
28
8802
                  "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
28
8803
28
8804
    constexpr int      kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
28
8805
    constexpr int      kBias      = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
28
8806
    constexpr int      kMinExp    = 1 - kBias;
28
8807
    constexpr uint64_t kHiddenBit = uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
28
8808
28
8809
    using bits_type = typename std::conditional< kPrecision == 24, uint32_t, uint64_t >::type;
28
8810
28
8811
    const uint64_t bits = reinterpret_bits<bits_type>(value);
28
8812
    const uint64_t E = bits >> (kPrecision - 1);
28
8813
    const uint64_t F = bits & (kHiddenBit - 1);
28
8814
28
8815
    const bool is_denormal = (E == 0);
28
8816
    const diyfp v = is_denormal
0
8817
                    ? diyfp(F, kMinExp)
28
8818
                    : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
28
8819
28
8820
    // Compute the boundaries m- and m+ of the floating-point value
28
8821
    // v = f * 2^e.
28
8822
    //
28
8823
    // Determine v- and v+, the floating-point predecessor and successor if v,
28
8824
    // respectively.
28
8825
    //
28
8826
    //      v- = v - 2^e        if f != 2^(p-1) or e == e_min                (A)
28
8827
    //         = v - 2^(e-1)    if f == 2^(p-1) and e > e_min                (B)
28
8828
    //
28
8829
    //      v+ = v + 2^e
28
8830
    //
28
8831
    // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
28
8832
    // between m- and m+ round to v, regardless of how the input rounding
28
8833
    // algorithm breaks ties.
28
8834
    //
28
8835
    //      ---+-------------+-------------+-------------+-------------+---  (A)
28
8836
    //         v-            m-            v             m+            v+
28
8837
    //
28
8838
    //      -----------------+------+------+-------------+-------------+---  (B)
28
8839
    //                       v-     m-     v             m+            v+
28
8840
0
8841
    const bool lower_boundary_is_closer = (F == 0 and E > 1);
28
8842
    const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
28
8843
    const diyfp m_minus = lower_boundary_is_closer
0
8844
                          ? diyfp(4 * v.f - 1, v.e - 2)  // (B)
28
8845
                          : diyfp(2 * v.f - 1, v.e - 1); // (A)
28
8846
28
8847
    // Determine the normalized w+ = m+.
28
8848
    const diyfp w_plus = diyfp::normalize(m_plus);
28
8849
28
8850
    // Determine w- = m- such that e_(w-) = e_(w+).
28
8851
    const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
28
8852
28
8853
    return {diyfp::normalize(v), w_minus, w_plus};
28
8854
}
8855
8856
// Given normalized diyfp w, Grisu needs to find a (normalized) cached
8857
// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
8858
// within a certain range [alpha, gamma] (Definition 3.2 from [1])
8859
//
8860
//      alpha <= e = e_c + e_w + q <= gamma
8861
//
8862
// or
8863
//
8864
//      f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
8865
//                          <= f_c * f_w * 2^gamma
8866
//
8867
// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
8868
//
8869
//      2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
8870
//
8871
// or
8872
//
8873
//      2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
8874
//
8875
// The choice of (alpha,gamma) determines the size of the table and the form of
8876
// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
8877
// in practice:
8878
//
8879
// The idea is to cut the number c * w = f * 2^e into two parts, which can be
8880
// processed independently: An integral part p1, and a fractional part p2:
8881
//
8882
//      f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
8883
//              = (f div 2^-e) + (f mod 2^-e) * 2^e
8884
//              = p1 + p2 * 2^e
8885
//
8886
// The conversion of p1 into decimal form requires a series of divisions and
8887
// modulos by (a power of) 10. These operations are faster for 32-bit than for
8888
// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
8889
// achieved by choosing
8890
//
8891
//      -e >= 32   or   e <= -32 := gamma
8892
//
8893
// In order to convert the fractional part
8894
//
8895
//      p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
8896
//
8897
// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
8898
// d[-i] are extracted in order:
8899
//
8900
//      (10 * p2) div 2^-e = d[-1]
8901
//      (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
8902
//
8903
// The multiplication by 10 must not overflow. It is sufficient to choose
8904
//
8905
//      10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
8906
//
8907
// Since p2 = f mod 2^-e < 2^-e,
8908
//
8909
//      -e <= 60   or   e >= -60 := alpha
8910
8911
constexpr int kAlpha = -60;
8912
constexpr int kGamma = -32;
8913
8914
struct cached_power // c = f * 2^e ~= 10^k
8915
{
8916
    uint64_t f;
8917
    int e;
8918
    int k;
8919
};
8920
8921
/*!
8922
For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
8923
power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
8924
satisfies (Definition 3.2 from [1])
8925
8926
     alpha <= e_c + e + q <= gamma.
8927
*/
8928
inline cached_power get_cached_power_for_binary_exponent(int e)
28
8929
{
28
8930
    // Now
28
8931
    //
28
8932
    //      alpha <= e_c + e + q <= gamma                                    (1)
28
8933
    //      ==> f_c * 2^alpha <= c * 2^e * 2^q
28
8934
    //
28
8935
    // and since the c's are normalized, 2^(q-1) <= f_c,
28
8936
    //
28
8937
    //      ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
28
8938
    //      ==> 2^(alpha - e - 1) <= c
28
8939
    //
28
8940
    // If c were an exakt power of ten, i.e. c = 10^k, one may determine k as
28
8941
    //
28
8942
    //      k = ceil( log_10( 2^(alpha - e - 1) ) )
28
8943
    //        = ceil( (alpha - e - 1) * log_10(2) )
28
8944
    //
28
8945
    // From the paper:
28
8946
    // "In theory the result of the procedure could be wrong since c is rounded,
28
8947
    //  and the computation itself is approximated [...]. In practice, however,
28
8948
    //  this simple function is sufficient."
28
8949
    //
28
8950
    // For IEEE double precision floating-point numbers converted into
28
8951
    // normalized diyfp's w = f * 2^e, with q = 64,
28
8952
    //
28
8953
    //      e >= -1022      (min IEEE exponent)
28
8954
    //           -52        (p - 1)
28
8955
    //           -52        (p - 1, possibly normalize denormal IEEE numbers)
28
8956
    //           -11        (normalize the diyfp)
28
8957
    //         = -1137
28
8958
    //
28
8959
    // and
28
8960
    //
28
8961
    //      e <= +1023      (max IEEE exponent)
28
8962
    //           -52        (p - 1)
28
8963
    //           -11        (normalize the diyfp)
28
8964
    //         = 960
28
8965
    //
28
8966
    // This binary exponent range [-1137,960] results in a decimal exponent
28
8967
    // range [-307,324]. One does not need to store a cached power for each
28
8968
    // k in this range. For each such k it suffices to find a cached power
28
8969
    // such that the exponent of the product lies in [alpha,gamma].
28
8970
    // This implies that the difference of the decimal exponents of adjacent
28
8971
    // table entries must be less than or equal to
28
8972
    //
28
8973
    //      floor( (gamma - alpha) * log_10(2) ) = 8.
28
8974
    //
28
8975
    // (A smaller distance gamma-alpha would require a larger table.)
28
8976
28
8977
    // NB:
28
8978
    // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
28
8979
28
8980
    constexpr int kCachedPowersSize = 79;
28
8981
    constexpr int kCachedPowersMinDecExp = -300;
28
8982
    constexpr int kCachedPowersDecStep = 8;
28
8983
28
8984
    static constexpr cached_power kCachedPowers[] =
28
8985
    {
28
8986
        { 0xAB70FE17C79AC6CA, -1060, -300 },
28
8987
        { 0xFF77B1FCBEBCDC4F, -1034, -292 },
28
8988
        { 0xBE5691EF416BD60C, -1007, -284 },
28
8989
        { 0x8DD01FAD907FFC3C,  -980, -276 },
28
8990
        { 0xD3515C2831559A83,  -954, -268 },
28
8991
        { 0x9D71AC8FADA6C9B5,  -927, -260 },
28
8992
        { 0xEA9C227723EE8BCB,  -901, -252 },
28
8993
        { 0xAECC49914078536D,  -874, -244 },
28
8994
        { 0x823C12795DB6CE57,  -847, -236 },
28
8995
        { 0xC21094364DFB5637,  -821, -228 },
28
8996
        { 0x9096EA6F3848984F,  -794, -220 },
28
8997
        { 0xD77485CB25823AC7,  -768, -212 },
28
8998
        { 0xA086CFCD97BF97F4,  -741, -204 },
28
8999
        { 0xEF340A98172AACE5,  -715, -196 },
28
9000
        { 0xB23867FB2A35B28E,  -688, -188 },
28
9001
        { 0x84C8D4DFD2C63F3B,  -661, -180 },
28
9002
        { 0xC5DD44271AD3CDBA,  -635, -172 },
28
9003
        { 0x936B9FCEBB25C996,  -608, -164 },
28
9004
        { 0xDBAC6C247D62A584,  -582, -156 },
28
9005
        { 0xA3AB66580D5FDAF6,  -555, -148 },
28
9006
        { 0xF3E2F893DEC3F126,  -529, -140 },
28
9007
        { 0xB5B5ADA8AAFF80B8,  -502, -132 },
28
9008
        { 0x87625F056C7C4A8B,  -475, -124 },
28
9009
        { 0xC9BCFF6034C13053,  -449, -116 },
28
9010
        { 0x964E858C91BA2655,  -422, -108 },
28
9011
        { 0xDFF9772470297EBD,  -396, -100 },
28
9012
        { 0xA6DFBD9FB8E5B88F,  -369,  -92 },
28
9013
        { 0xF8A95FCF88747D94,  -343,  -84 },
28
9014
        { 0xB94470938FA89BCF,  -316,  -76 },
28
9015
        { 0x8A08F0F8BF0F156B,  -289,  -68 },
28
9016
        { 0xCDB02555653131B6,  -263,  -60 },
28
9017
        { 0x993FE2C6D07B7FAC,  -236,  -52 },
28
9018
        { 0xE45C10C42A2B3B06,  -210,  -44 },
28
9019
        { 0xAA242499697392D3,  -183,  -36 },
28
9020
        { 0xFD87B5F28300CA0E,  -157,  -28 },
28
9021
        { 0xBCE5086492111AEB,  -130,  -20 },
28
9022
        { 0x8CBCCC096F5088CC,  -103,  -12 },
28
9023
        { 0xD1B71758E219652C,   -77,   -4 },
28
9024
        { 0x9C40000000000000,   -50,    4 },
28
9025
        { 0xE8D4A51000000000,   -24,   12 },
28
9026
        { 0xAD78EBC5AC620000,     3,   20 },
28
9027
        { 0x813F3978F8940984,    30,   28 },
28
9028
        { 0xC097CE7BC90715B3,    56,   36 },
28
9029
        { 0x8F7E32CE7BEA5C70,    83,   44 },
28
9030
        { 0xD5D238A4ABE98068,   109,   52 },
28
9031
        { 0x9F4F2726179A2245,   136,   60 },
28
9032
        { 0xED63A231D4C4FB27,   162,   68 },
28
9033
        { 0xB0DE65388CC8ADA8,   189,   76 },
28
9034
        { 0x83C7088E1AAB65DB,   216,   84 },
28
9035
        { 0xC45D1DF942711D9A,   242,   92 },
28
9036
        { 0x924D692CA61BE758,   269,  100 },
28
9037
        { 0xDA01EE641A708DEA,   295,  108 },
28
9038
        { 0xA26DA3999AEF774A,   322,  116 },
28
9039
        { 0xF209787BB47D6B85,   348,  124 },
28
9040
        { 0xB454E4A179DD1877,   375,  132 },
28
9041
        { 0x865B86925B9BC5C2,   402,  140 },
28
9042
        { 0xC83553C5C8965D3D,   428,  148 },
28
9043
        { 0x952AB45CFA97A0B3,   455,  156 },
28
9044
        { 0xDE469FBD99A05FE3,   481,  164 },
28
9045
        { 0xA59BC234DB398C25,   508,  172 },
28
9046
        { 0xF6C69A72A3989F5C,   534,  180 },
28
9047
        { 0xB7DCBF5354E9BECE,   561,  188 },
28
9048
        { 0x88FCF317F22241E2,   588,  196 },
28
9049
        { 0xCC20CE9BD35C78A5,   614,  204 },
28
9050
        { 0x98165AF37B2153DF,   641,  212 },
28
9051
        { 0xE2A0B5DC971F303A,   667,  220 },
28
9052
        { 0xA8D9D1535CE3B396,   694,  228 },
28
9053
        { 0xFB9B7CD9A4A7443C,   720,  236 },
28
9054
        { 0xBB764C4CA7A44410,   747,  244 },
28
9055
        { 0x8BAB8EEFB6409C1A,   774,  252 },
28
9056
        { 0xD01FEF10A657842C,   800,  260 },
28
9057
        { 0x9B10A4E5E9913129,   827,  268 },
28
9058
        { 0xE7109BFBA19C0C9D,   853,  276 },
28
9059
        { 0xAC2820D9623BF429,   880,  284 },
28
9060
        { 0x80444B5E7AA7CF85,   907,  292 },
28
9061
        { 0xBF21E44003ACDD2D,   933,  300 },
28
9062
        { 0x8E679C2F5E44FF8F,   960,  308 },
28
9063
        { 0xD433179D9C8CB841,   986,  316 },
28
9064
        { 0x9E19DB92B4E31BA9,  1013,  324 },
28
9065
    };
28
9066
28
9067
    // This computation gives exactly the same results for k as
28
9068
    //      k = ceil((kAlpha - e - 1) * 0.30102999566398114)
28
9069
    // for |e| <= 1500, but doesn't require floating-point operations.
28
9070
    // NB: log_10(2) ~= 78913 / 2^18
28
9071
    assert(e >= -1500);
28
9072
    assert(e <=  1500);
28
9073
    const int f = kAlpha - e - 1;
28
9074
    const int k = (f * 78913) / (1 << 18) + (f > 0);
28
9075
28
9076
    const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
28
9077
    assert(index >= 0);
28
9078
    assert(index < kCachedPowersSize);
28
9079
    static_cast<void>(kCachedPowersSize); // Fix warning.
28
9080
28
9081
    const cached_power cached = kCachedPowers[index];
28
9082
    assert(kAlpha <= cached.e + e + 64);
28
9083
    assert(kGamma >= cached.e + e + 64);
28
9084
28
9085
    return cached;
28
9086
}
9087
9088
/*!
9089
For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
9090
For n == 0, returns 1 and sets pow10 := 1.
9091
*/
9092
inline int find_largest_pow10(const uint32_t n, uint32_t& pow10)
28
9093
{
28
9094
    // LCOV_EXCL_START
28
9095
    if (n >= 1000000000)
0
9096
    {
0
9097
        pow10 = 1000000000;
0
9098
        return 10;
0
9099
    }
28
9100
    // LCOV_EXCL_STOP
28
9101
    else if (n >= 100000000)
0
9102
    {
0
9103
        pow10 = 100000000;
0
9104
        return  9;
0
9105
    }
28
9106
    else if (n >= 10000000)
0
9107
    {
0
9108
        pow10 = 10000000;
0
9109
        return  8;
0
9110
    }
28
9111
    else if (n >= 1000000)
0
9112
    {
0
9113
        pow10 = 1000000;
0
9114
        return  7;
0
9115
    }
28
9116
    else if (n >= 100000)
24
9117
    {
24
9118
        pow10 = 100000;
24
9119
        return  6;
24
9120
    }
4
9121
    else if (n >= 10000)
4
9122
    {
4
9123
        pow10 = 10000;
4
9124
        return  5;
4
9125
    }
0
9126
    else if (n >= 1000)
0
9127
    {
0
9128
        pow10 = 1000;
0
9129
        return  4;
0
9130
    }
0
9131
    else if (n >= 100)
0
9132
    {
0
9133
        pow10 = 100;
0
9134
        return  3;
0
9135
    }
0
9136
    else if (n >= 10)
0
9137
    {
0
9138
        pow10 = 10;
0
9139
        return  2;
0
9140
    }
0
9141
    else
0
9142
    {
0
9143
        pow10 = 1;
0
9144
        return 1;
0
9145
    }
28
9146
}
9147
9148
inline void grisu2_round(char* buf, int len, uint64_t dist, uint64_t delta,
9149
                         uint64_t rest, uint64_t ten_k)
28
9150
{
28
9151
    assert(len >= 1);
28
9152
    assert(dist <= delta);
28
9153
    assert(rest <= delta);
28
9154
    assert(ten_k > 0);
28
9155
28
9156
    //               <--------------------------- delta ---->
28
9157
    //                                  <---- dist --------->
28
9158
    // --------------[------------------+-------------------]--------------
28
9159
    //               M-                 w                   M+
28
9160
    //
28
9161
    //                                  ten_k
28
9162
    //                                <------>
28
9163
    //                                       <---- rest ---->
28
9164
    // --------------[------------------+----+--------------]--------------
28
9165
    //                                  w    V
28
9166
    //                                       = buf * 10^k
28
9167
    //
28
9168
    // ten_k represents a unit-in-the-last-place in the decimal representation
28
9169
    // stored in buf.
28
9170
    // Decrement buf by ten_k while this takes buf closer to w.
28
9171
28
9172
    // The tests are written in this order to avoid overflow in unsigned
28
9173
    // integer arithmetic.
28
9174
28
9175
    while (rest < dist
16
9176
            and delta - rest >= ten_k
0
9177
            and (rest + ten_k < dist or dist - rest > rest + ten_k - dist))
0
9178
    {
0
9179
        assert(buf[len - 1] != '0');
0
9180
        buf[len - 1]--;
0
9181
        rest += ten_k;
0
9182
    }
28
9183
}
9184
9185
/*!
9186
Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
9187
M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
9188
*/
9189
inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
9190
                             diyfp M_minus, diyfp w, diyfp M_plus)
28
9191
{
28
9192
    static_assert(kAlpha >= -60, "internal error");
28
9193
    static_assert(kGamma <= -32, "internal error");
28
9194
28
9195
    // Generates the digits (and the exponent) of a decimal floating-point
28
9196
    // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
28
9197
    // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
28
9198
    //
28
9199
    //               <--------------------------- delta ---->
28
9200
    //                                  <---- dist --------->
28
9201
    // --------------[------------------+-------------------]--------------
28
9202
    //               M-                 w                   M+
28
9203
    //
28
9204
    // Grisu2 generates the digits of M+ from left to right and stops as soon as
28
9205
    // V is in [M-,M+].
28
9206
28
9207
    assert(M_plus.e >= kAlpha);
28
9208
    assert(M_plus.e <= kGamma);
28
9209
28
9210
    uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
28
9211
    uint64_t dist  = diyfp::sub(M_plus, w      ).f; // (significand of (M+ - w ), implicit exponent is e)
28
9212
28
9213
    // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
28
9214
    //
28
9215
    //      M+ = f * 2^e
28
9216
    //         = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
28
9217
    //         = ((p1        ) * 2^-e + (p2        )) * 2^e
28
9218
    //         = p1 + p2 * 2^e
28
9219
28
9220
    const diyfp one(uint64_t{1} << -M_plus.e, M_plus.e);
28
9221
28
9222
    uint32_t p1 = static_cast<uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
28
9223
    uint64_t p2 = M_plus.f & (one.f - 1);                    // p2 = f mod 2^-e
28
9224
28
9225
    // 1)
28
9226
    //
28
9227
    // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
28
9228
28
9229
    assert(p1 > 0);
28
9230
28
9231
    uint32_t pow10;
28
9232
    const int k = find_largest_pow10(p1, pow10);
28
9233
28
9234
    //      10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
28
9235
    //
28
9236
    //      p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
28
9237
    //         = (d[k-1]         ) * 10^(k-1) + (p1 mod 10^(k-1))
28
9238
    //
28
9239
    //      M+ = p1                                             + p2 * 2^e
28
9240
    //         = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1))          + p2 * 2^e
28
9241
    //         = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
28
9242
    //         = d[k-1] * 10^(k-1) + (                         rest) * 2^e
28
9243
    //
28
9244
    // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
28
9245
    //
28
9246
    //      p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
28
9247
    //
28
9248
    // but stop as soon as
28
9249
    //
28
9250
    //      rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
28
9251
28
9252
    int n = k;
164
9253
    while (n > 0)
148
9254
    {
148
9255
        // Invariants:
148
9256
        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)    (buffer = 0 for n = k)
148
9257
        //      pow10 = 10^(n-1) <= p1 < 10^n
148
9258
        //
148
9259
        const uint32_t d = p1 / pow10;  // d = p1 div 10^(n-1)
148
9260
        const uint32_t r = p1 % pow10;  // r = p1 mod 10^(n-1)
148
9261
        //
148
9262
        //      M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
148
9263
        //         = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
148
9264
        //
148
9265
        assert(d <= 9);
148
9266
        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
148
9267
        //
148
9268
        //      M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
148
9269
        //
148
9270
        p1 = r;
148
9271
        n--;
148
9272
        //
148
9273
        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)
148
9274
        //      pow10 = 10^n
148
9275
        //
148
9276
148
9277
        // Now check if enough digits have been generated.
148
9278
        // Compute
148
9279
        //
148
9280
        //      p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
148
9281
        //
148
9282
        // Note:
148
9283
        // Since rest and delta share the same exponent e, it suffices to
148
9284
        // compare the significands.
148
9285
        const uint64_t rest = (uint64_t{p1} << -one.e) + p2;
148
9286
        if (rest <= delta)
12
9287
        {
12
9288
            // V = buffer * 10^n, with M- <= V <= M+.
12
9289
12
9290
            decimal_exponent += n;
12
9291
12
9292
            // We may now just stop. But instead look if the buffer could be
12
9293
            // decremented to bring V closer to w.
12
9294
            //
12
9295
            // pow10 = 10^n is now 1 ulp in the decimal representation V.
12
9296
            // The rounding procedure works with diyfp's with an implicit
12
9297
            // exponent of e.
12
9298
            //
12
9299
            //      10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
12
9300
            //
12
9301
            const uint64_t ten_n = uint64_t{pow10} << -one.e;
12
9302
            grisu2_round(buffer, length, dist, delta, rest, ten_n);
12
9303
12
9304
            return;
12
9305
        }
148
9306
136
9307
        pow10 /= 10;
136
9308
        //
136
9309
        //      pow10 = 10^(n-1) <= p1 < 10^n
136
9310
        // Invariants restored.
136
9311
    }
28
9312
28
9313
    // 2)
28
9314
    //
28
9315
    // The digits of the integral part have been generated:
28
9316
    //
28
9317
    //      M+ = d[k-1]...d[1]d[0] + p2 * 2^e
28
9318
    //         = buffer            + p2 * 2^e
28
9319
    //
28
9320
    // Now generate the digits of the fractional part p2 * 2^e.
28
9321
    //
28
9322
    // Note:
28
9323
    // No decimal point is generated: the exponent is adjusted instead.
28
9324
    //
28
9325
    // p2 actually represents the fraction
28
9326
    //
28
9327
    //      p2 * 2^e
28
9328
    //          = p2 / 2^-e
28
9329
    //          = d[-1] / 10^1 + d[-2] / 10^2 + ...
28
9330
    //
28
9331
    // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
28
9332
    //
28
9333
    //      p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
28
9334
    //                      + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
28
9335
    //
28
9336
    // using
28
9337
    //
28
9338
    //      10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
28
9339
    //                = (                   d) * 2^-e + (                   r)
28
9340
    //
28
9341
    // or
28
9342
    //      10^m * p2 * 2^e = d + r * 2^e
28
9343
    //
28
9344
    // i.e.
28
9345
    //
28
9346
    //      M+ = buffer + p2 * 2^e
28
9347
    //         = buffer + 10^-m * (d + r * 2^e)
28
9348
    //         = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
28
9349
    //
28
9350
    // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
28
9351
16
9352
    assert(p2 > delta);
16
9353
16
9354
    int m = 0;
16
9355
    for (;;)
16
9356
    {
16
9357
        // Invariant:
16
9358
        //      M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
16
9359
        //         = buffer * 10^-m + 10^-m * (p2                                 ) * 2^e
16
9360
        //         = buffer * 10^-m + 10^-m * (1/10 * (10 * p2)                   ) * 2^e
16
9361
        //         = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
16
9362
        //
16
9363
        assert(p2 <= UINT64_MAX / 10);
16
9364
        p2 *= 10;
16
9365
        const uint64_t d = p2 >> -one.e;     // d = (10 * p2) div 2^-e
16
9366
        const uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
16
9367
        //
16
9368
        //      M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
16
9369
        //         = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
16
9370
        //         = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
16
9371
        //
16
9372
        assert(d <= 9);
16
9373
        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
16
9374
        //
16
9375
        //      M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
16
9376
        //
16
9377
        p2 = r;
16
9378
        m++;
16
9379
        //
16
9380
        //      M+ = buffer * 10^-m + 10^-m * p2 * 2^e
16
9381
        // Invariant restored.
16
9382
16
9383
        // Check if enough digits have been generated.
16
9384
        //
16
9385
        //      10^-m * p2 * 2^e <= delta * 2^e
16
9386
        //              p2 * 2^e <= 10^m * delta * 2^e
16
9387
        //                    p2 <= 10^m * delta
16
9388
        delta *= 10;
16
9389
        dist  *= 10;
16
9390
        if (p2 <= delta)
16
9391
        {
16
9392
            break;
16
9393
        }
16
9394
    }
16
9395
16
9396
    // V = buffer * 10^-m, with M- <= V <= M+.
16
9397
16
9398
    decimal_exponent -= m;
16
9399
16
9400
    // 1 ulp in the decimal representation is now 10^-m.
16
9401
    // Since delta and dist are now scaled by 10^m, we need to do the
16
9402
    // same with ulp in order to keep the units in sync.
16
9403
    //
16
9404
    //      10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
16
9405
    //
16
9406
    const uint64_t ten_m = one.f;
16
9407
    grisu2_round(buffer, length, dist, delta, p2, ten_m);
16
9408
16
9409
    // By construction this algorithm generates the shortest possible decimal
16
9410
    // number (Loitsch, Theorem 6.2) which rounds back to w.
16
9411
    // For an input number of precision p, at least
16
9412
    //
16
9413
    //      N = 1 + ceil(p * log_10(2))
16
9414
    //
16
9415
    // decimal digits are sufficient to identify all binary floating-point
16
9416
    // numbers (Matula, "In-and-Out conversions").
16
9417
    // This implies that the algorithm does not produce more than N decimal
16
9418
    // digits.
16
9419
    //
16
9420
    //      N = 17 for p = 53 (IEEE double precision)
16
9421
    //      N = 9  for p = 24 (IEEE single precision)
16
9422
}
9423
9424
/*!
9425
v = buf * 10^decimal_exponent
9426
len is the length of the buffer (number of decimal digits)
9427
The buffer must be large enough, i.e. >= max_digits10.
9428
*/
9429
inline void grisu2(char* buf, int& len, int& decimal_exponent,
9430
                   diyfp m_minus, diyfp v, diyfp m_plus)
28
9431
{
28
9432
    assert(m_plus.e == m_minus.e);
28
9433
    assert(m_plus.e == v.e);
28
9434
28
9435
    //  --------(-----------------------+-----------------------)--------    (A)
28
9436
    //          m-                      v                       m+
28
9437
    //
28
9438
    //  --------------------(-----------+-----------------------)--------    (B)
28
9439
    //                      m-          v                       m+
28
9440
    //
28
9441
    // First scale v (and m- and m+) such that the exponent is in the range
28
9442
    // [alpha, gamma].
28
9443
28
9444
    const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
28
9445
28
9446
    const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
28
9447
28
9448
    // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
28
9449
    const diyfp w       = diyfp::mul(v,       c_minus_k);
28
9450
    const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
28
9451
    const diyfp w_plus  = diyfp::mul(m_plus,  c_minus_k);
28
9452
28
9453
    //  ----(---+---)---------------(---+---)---------------(---+---)----
28
9454
    //          w-                      w                       w+
28
9455
    //          = c*m-                  = c*v                   = c*m+
28
9456
    //
28
9457
    // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
28
9458
    // w+ are now off by a small amount.
28
9459
    // In fact:
28
9460
    //
28
9461
    //      w - v * 10^k < 1 ulp
28
9462
    //
28
9463
    // To account for this inaccuracy, add resp. subtract 1 ulp.
28
9464
    //
28
9465
    //  --------+---[---------------(---+---)---------------]---+--------
28
9466
    //          w-  M-                  w                   M+  w+
28
9467
    //
28
9468
    // Now any number in [M-, M+] (bounds included) will round to w when input,
28
9469
    // regardless of how the input rounding algorithm breaks ties.
28
9470
    //
28
9471
    // And digit_gen generates the shortest possible such number in [M-, M+].
28
9472
    // Note that this does not mean that Grisu2 always generates the shortest
28
9473
    // possible number in the interval (m-, m+).
28
9474
    const diyfp M_minus(w_minus.f + 1, w_minus.e);
28
9475
    const diyfp M_plus (w_plus.f  - 1, w_plus.e );
28
9476
28
9477
    decimal_exponent = -cached.k; // = -(-k) = k
28
9478
28
9479
    grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
28
9480
}
9481
9482
/*!
9483
v = buf * 10^decimal_exponent
9484
len is the length of the buffer (number of decimal digits)
9485
The buffer must be large enough, i.e. >= max_digits10.
9486
*/
9487
template <typename FloatType>
9488
void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
28
9489
{
28
9490
    static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
28
9491
                  "internal error: not enough precision");
28
9492
28
9493
    assert(std::isfinite(value));
28
9494
    assert(value > 0);
28
9495
28
9496
    // If the neighbors (and boundaries) of 'value' are always computed for double-precision
28
9497
    // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
28
9498
    // decimal representations are not exactly "short".
28
9499
    //
28
9500
    // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
28
9501
    // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
28
9502
    // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
28
9503
    // does.
28
9504
    // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
28
9505
    // representation using the corresponding std::from_chars function recovers value exactly". That
28
9506
    // indicates that single precision floating-point numbers should be recovered using
28
9507
    // 'std::strtof'.
28
9508
    //
28
9509
    // NB: If the neighbors are computed for single-precision numbers, there is a single float
28
9510
    //     (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
28
9511
    //     value is off by 1 ulp.
28
9512
#if 0
9513
    const boundaries w = compute_boundaries(static_cast<double>(value));
9514
#else
28
9515
    const boundaries w = compute_boundaries(value);
28
9516
#endif
28
9517
28
9518
    grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
28
9519
}
9520
9521
/*!
9522
@brief appends a decimal representation of e to buf
9523
@return a pointer to the element following the exponent.
9524
@pre -1000 < e < 1000
9525
*/
9526
inline char* append_exponent(char* buf, int e)
0
9527
{
0
9528
    assert(e > -1000);
0
9529
    assert(e <  1000);
0
9530
0
9531
    if (e < 0)
0
9532
    {
0
9533
        e = -e;
0
9534
        *buf++ = '-';
0
9535
    }
0
9536
    else
0
9537
    {
0
9538
        *buf++ = '+';
0
9539
    }
0
9540
0
9541
    uint32_t k = static_cast<uint32_t>(e);
0
9542
    if (k < 10)
0
9543
    {
0
9544
        // Always print at least two digits in the exponent.
0
9545
        // This is for compatibility with printf("%g").
0
9546
        *buf++ = '0';
0
9547
        *buf++ = static_cast<char>('0' + k);
0
9548
    }
0
9549
    else if (k < 100)
0
9550
    {
0
9551
        *buf++ = static_cast<char>('0' + k / 10);
0
9552
        k %= 10;
0
9553
        *buf++ = static_cast<char>('0' + k);
0
9554
    }
0
9555
    else
0
9556
    {
0
9557
        *buf++ = static_cast<char>('0' + k / 100);
0
9558
        k %= 100;
0
9559
        *buf++ = static_cast<char>('0' + k / 10);
0
9560
        k %= 10;
0
9561
        *buf++ = static_cast<char>('0' + k);
0
9562
    }
0
9563
0
9564
    return buf;
0
9565
}
9566
9567
/*!
9568
@brief prettify v = buf * 10^decimal_exponent
9569
9570
If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
9571
notation. Otherwise it will be printed in exponential notation.
9572
9573
@pre min_exp < 0
9574
@pre max_exp > 0
9575
*/
9576
inline char* format_buffer(char* buf, int len, int decimal_exponent,
9577
                           int min_exp, int max_exp)
28
9578
{
28
9579
    assert(min_exp < 0);
28
9580
    assert(max_exp > 0);
28
9581
28
9582
    const int k = len;
28
9583
    const int n = len + decimal_exponent;
28
9584
28
9585
    // v = buf * 10^(n-k)
28
9586
    // k is the length of the buffer (number of decimal digits)
28
9587
    // n is the position of the decimal point relative to the start of the buffer.
28
9588
28
9589
    if (k <= n and n <= max_exp)
0
9590
    {
0
9591
        // digits[000]
0
9592
        // len <= max_exp + 2
0
9593
0
9594
        std::memset(buf + k, '0', static_cast<size_t>(n - k));
0
9595
        // Make it look like a floating-point number (#362, #378)
0
9596
        buf[n + 0] = '.';
0
9597
        buf[n + 1] = '0';
0
9598
        return buf + (n + 2);
0
9599
    }
28
9600
28
9601
    if (0 < n and n <= max_exp)
28
9602
    {
28
9603
        // dig.its
28
9604
        // len <= max_digits10 + 1
28
9605
28
9606
        assert(k > n);
28
9607
28
9608
        std::memmove(buf + (n + 1), buf + n, static_cast<size_t>(k - n));
28
9609
        buf[n] = '.';
28
9610
        return buf + (k + 1);
28
9611
    }
28
9612
0
9613
    if (min_exp < n and n <= 0)
0
9614
    {
0
9615
        // 0.[000]digits
0
9616
        // len <= 2 + (-min_exp - 1) + max_digits10
0
9617
0
9618
        std::memmove(buf + (2 + -n), buf, static_cast<size_t>(k));
0
9619
        buf[0] = '0';
0
9620
        buf[1] = '.';
0
9621
        std::memset(buf + 2, '0', static_cast<size_t>(-n));
0
9622
        return buf + (2 + (-n) + k);
0
9623
    }
0
9624
0
9625
    if (k == 1)
0
9626
    {
0
9627
        // dE+123
0
9628
        // len <= 1 + 5
0
9629
0
9630
        buf += 1;
0
9631
    }
0
9632
    else
0
9633
    {
0
9634
        // d.igitsE+123
0
9635
        // len <= max_digits10 + 1 + 5
0
9636
0
9637
        std::memmove(buf + 2, buf + 1, static_cast<size_t>(k - 1));
0
9638
        buf[1] = '.';
0
9639
        buf += 1 + k;
0
9640
    }
0
9641
0
9642
    *buf++ = 'e';
0
9643
    return append_exponent(buf, n - 1);
0
9644
}
9645
9646
} // namespace dtoa_impl
9647
9648
/*!
9649
@brief generates a decimal representation of the floating-point number value in [first, last).
9650
9651
The format of the resulting decimal representation is similar to printf's %g
9652
format. Returns an iterator pointing past-the-end of the decimal representation.
9653
9654
@note The input number must be finite, i.e. NaN's and Inf's are not supported.
9655
@note The buffer must be large enough.
9656
@note The result is NOT null-terminated.
9657
*/
9658
template <typename FloatType>
9659
char* to_chars(char* first, char* last, FloatType value)
28
9660
{
28
9661
    static_cast<void>(last); // maybe unused - fix warning
28
9662
    assert(std::isfinite(value));
28
9663
28
9664
    // Use signbit(value) instead of (value < 0) since signbit works for -0.
28
9665
    if (std::signbit(value))
0
9666
    {
0
9667
        value = -value;
0
9668
        *first++ = '-';
0
9669
    }
28
9670
28
9671
    if (value == 0) // +-0
0
9672
    {
0
9673
        *first++ = '0';
0
9674
        // Make it look like a floating-point number (#362, #378)
0
9675
        *first++ = '.';
0
9676
        *first++ = '0';
0
9677
        return first;
0
9678
    }
28
9679
28
9680
    assert(last - first >= std::numeric_limits<FloatType>::max_digits10);
28
9681
28
9682
    // Compute v = buffer * 10^decimal_exponent.
28
9683
    // The decimal digits are stored in the buffer, which needs to be interpreted
28
9684
    // as an unsigned decimal integer.
28
9685
    // len is the length of the buffer, i.e. the number of decimal digits.
28
9686
    int len = 0;
28
9687
    int decimal_exponent = 0;
28
9688
    dtoa_impl::grisu2(first, len, decimal_exponent, value);
28
9689
28
9690
    assert(len <= std::numeric_limits<FloatType>::max_digits10);
28
9691
28
9692
    // Format the buffer like printf("%.*g", prec, value)
28
9693
    constexpr int kMinExp = -4;
28
9694
    // Use digits10 here to increase compatibility with version 2.
28
9695
    constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
28
9696
28
9697
    assert(last - first >= kMaxExp + 2);
28
9698
    assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
28
9699
    assert(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
28
9700
28
9701
    return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
28
9702
}
9703
9704
} // namespace detail
9705
} // namespace nlohmann
9706
9707
// #include <nlohmann/detail/macro_scope.hpp>
9708
9709
// #include <nlohmann/detail/meta/cpp_future.hpp>
9710
9711
// #include <nlohmann/detail/output/output_adapters.hpp>
9712
9713
// #include <nlohmann/detail/value_t.hpp>
9714
9715
9716
namespace nlohmann
9717
{
9718
namespace detail
9719
{
9720
///////////////////
9721
// serialization //
9722
///////////////////
9723
9724
template<typename BasicJsonType>
9725
class serializer
9726
{
9727
    using string_t = typename BasicJsonType::string_t;
9728
    using number_float_t = typename BasicJsonType::number_float_t;
9729
    using number_integer_t = typename BasicJsonType::number_integer_t;
9730
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9731
    static constexpr uint8_t UTF8_ACCEPT = 0;
9732
    static constexpr uint8_t UTF8_REJECT = 1;
9733
9734
  public:
9735
    /*!
9736
    @param[in] s  output stream to serialize to
9737
    @param[in] ichar  indentation character to use
9738
    */
9739
    serializer(output_adapter_t<char> s, const char ichar)
9740
        : o(std::move(s)), loc(std::localeconv()),
9741
          thousands_sep(loc->thousands_sep == nullptr ? '\0' : * (loc->thousands_sep)),
9742
          decimal_point(loc->decimal_point == nullptr ? '\0' : * (loc->decimal_point)),
9743
          indent_char(ichar), indent_string(512, indent_char)
440
9744
    {}
9745
9746
    // delete because of pointer members
9747
    serializer(const serializer&) = delete;
9748
    serializer& operator=(const serializer&) = delete;
9749
9750
    /*!
9751
    @brief internal implementation of the serialization function
9752
9753
    This function is called by the public member function dump and organizes
9754
    the serialization internally. The indentation level is propagated as
9755
    additional parameter. In case of arrays and objects, the function is
9756
    called recursively.
9757
9758
    - strings and object keys are escaped using `escape_string()`
9759
    - integer numbers are converted implicitly via `operator<<`
9760
    - floating-point numbers are converted to a string using `"%g"` format
9761
9762
    @param[in] val             value to serialize
9763
    @param[in] pretty_print    whether the output shall be pretty-printed
9764
    @param[in] indent_step     the indent level
9765
    @param[in] current_indent  the current indent level (only used internally)
9766
    */
9767
    void dump(const BasicJsonType& val, const bool pretty_print,
9768
              const bool ensure_ascii,
9769
              const unsigned int indent_step,
9770
              const unsigned int current_indent = 0)
9.51k
9771
    {
0
9772
        switch (val.m_type)
0
9773
        {
2.14k
9774
            case value_t::object:
2.14k
9775
            {
2.14k
9776
                if (val.m_value.object->empty())
0
9777
                {
0
9778
                    o->write_characters("{}", 2);
0
9779
                    return;
0
9780
                }
2.14k
9781
2.14k
9782
                if (pretty_print)
1.32k
9783
                {
1.32k
9784
                    o->write_characters("{\n", 2);
1.32k
9785
1.32k
9786
                    // variable to hold indentation for recursive calls
1.32k
9787
                    const auto new_indent = current_indent + indent_step;
1.32k
9788
                    if (JSON_UNLIKELY(indent_string.size() < new_indent))
0
9789
                    {
0
9790
                        indent_string.resize(indent_string.size() * 2, ' ');
0
9791
                    }
1.32k
9792
1.32k
9793
                    // first n-1 elements
1.32k
9794
                    auto i = val.m_value.object->cbegin();
6.27k
9795
                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
4.95k
9796
                    {
4.95k
9797
                        o->write_characters(indent_string.c_str(), new_indent);
4.95k
9798
                        o->write_character('\"');
4.95k
9799
                        dump_escaped(i->first, ensure_ascii);
4.95k
9800
                        o->write_characters("\": ", 3);
4.95k
9801
                        dump(i->second, true, ensure_ascii, indent_step, new_indent);
4.95k
9802
                        o->write_characters(",\n", 2);
4.95k
9803
                    }
1.32k
9804
1.32k
9805
                    // last element
1.32k
9806
                    assert(i != val.m_value.object->cend());
1.32k
9807
                    assert(std::next(i) == val.m_value.object->cend());
1.32k
9808
                    o->write_characters(indent_string.c_str(), new_indent);
1.32k
9809
                    o->write_character('\"');
1.32k
9810
                    dump_escaped(i->first, ensure_ascii);
1.32k
9811
                    o->write_characters("\": ", 3);
1.32k
9812
                    dump(i->second, true, ensure_ascii, indent_step, new_indent);
1.32k
9813
1.32k
9814
                    o->write_character('\n');
1.32k
9815
                    o->write_characters(indent_string.c_str(), current_indent);
1.32k
9816
                    o->write_character('}');
1.32k
9817
                }
2.14k
9818
                else
828
9819
                {
828
9820
                    o->write_character('{');
828
9821
828
9822
                    // first n-1 elements
828
9823
                    auto i = val.m_value.object->cbegin();
2.79k
9824
                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
1.96k
9825
                    {
1.96k
9826
                        o->write_character('\"');
1.96k
9827
                        dump_escaped(i->first, ensure_ascii);
1.96k
9828
                        o->write_characters("\":", 2);
1.96k
9829
                        dump(i->second, false, ensure_ascii, indent_step, current_indent);
1.96k
9830
                        o->write_character(',');
1.96k
9831
                    }
828
9832
828
9833
                    // last element
828
9834
                    assert(i != val.m_value.object->cend());
828
9835
                    assert(std::next(i) == val.m_value.object->cend());
828
9836
                    o->write_character('\"');
828
9837
                    dump_escaped(i->first, ensure_ascii);
828
9838
                    o->write_characters("\":", 2);
828
9839
                    dump(i->second, false, ensure_ascii, indent_step, current_indent);
828
9840
828
9841
                    o->write_character('}');
828
9842
                }
2.14k
9843
2.14k
9844
                return;
2.14k
9845
            }
2.14k
9846
4
9847
            case value_t::array:
4
9848
            {
4
9849
                if (val.m_value.array->empty())
0
9850
                {
0
9851
                    o->write_characters("[]", 2);
0
9852
                    return;
0
9853
                }
4
9854
4
9855
                if (pretty_print)
4
9856
                {
4
9857
                    o->write_characters("[\n", 2);
4
9858
4
9859
                    // variable to hold indentation for recursive calls
4
9860
                    const auto new_indent = current_indent + indent_step;
4
9861
                    if (JSON_UNLIKELY(indent_string.size() < new_indent))
0
9862
                    {
0
9863
                        indent_string.resize(indent_string.size() * 2, ' ');
0
9864
                    }
4
9865
4
9866
                    // first n-1 elements
4
9867
                    for (auto i = val.m_value.array->cbegin();
4
9868
                            i != val.m_value.array->cend() - 1; ++i)
0
9869
                    {
0
9870
                        o->write_characters(indent_string.c_str(), new_indent);
0
9871
                        dump(*i, true, ensure_ascii, indent_step, new_indent);
0
9872
                        o->write_characters(",\n", 2);
0
9873
                    }
4
9874
4
9875
                    // last element
4
9876
                    assert(not val.m_value.array->empty());
4
9877
                    o->write_characters(indent_string.c_str(), new_indent);
4
9878
                    dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
4
9879
4
9880
                    o->write_character('\n');
4
9881
                    o->write_characters(indent_string.c_str(), current_indent);
4
9882
                    o->write_character(']');
4
9883
                }
4
9884
                else
0
9885
                {
0
9886
                    o->write_character('[');
0
9887
0
9888
                    // first n-1 elements
0
9889
                    for (auto i = val.m_value.array->cbegin();
0
9890
                            i != val.m_value.array->cend() - 1; ++i)
0
9891
                    {
0
9892
                        dump(*i, false, ensure_ascii, indent_step, current_indent);
0
9893
                        o->write_character(',');
0
9894
                    }
0
9895
0
9896
                    // last element
0
9897
                    assert(not val.m_value.array->empty());
0
9898
                    dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
0
9899
0
9900
                    o->write_character(']');
0
9901
                }
4
9902
4
9903
                return;
4
9904
            }
4
9905
6.23k
9906
            case value_t::string:
6.23k
9907
            {
6.23k
9908
                o->write_character('\"');
6.23k
9909
                dump_escaped(*val.m_value.string, ensure_ascii);
6.23k
9910
                o->write_character('\"');
6.23k
9911
                return;
4
9912
            }
4
9913
8
9914
            case value_t::boolean:
8
9915
            {
8
9916
                if (val.m_value.boolean)
8
9917
                {
8
9918
                    o->write_characters("true", 4);
8
9919
                }
8
9920
                else
0
9921
                {
0
9922
                    o->write_characters("false", 5);
0
9923
                }
8
9924
                return;
4
9925
            }
4
9926
8
9927
            case value_t::number_integer:
8
9928
            {
8
9929
                dump_integer(val.m_value.number_integer);
8
9930
                return;
4
9931
            }
4
9932
1.02k
9933
            case value_t::number_unsigned:
1.02k
9934
            {
1.02k
9935
                dump_integer(val.m_value.number_unsigned);
1.02k
9936
                return;
4
9937
            }
4
9938
28
9939
            case value_t::number_float:
28
9940
            {
28
9941
                dump_float(val.m_value.number_float);
28
9942
                return;
4
9943
            }
4
9944
0
9945
            case value_t::discarded:
0
9946
            {
0
9947
                o->write_characters("<discarded>", 11);
0
9948
                return;
4
9949
            }
4
9950
56
9951
            case value_t::null:
56
9952
            {
56
9953
                o->write_characters("null", 4);
56
9954
                return;
4
9955
            }
0
9956
        }
9.51k
9957
    }
9958
9959
  private:
9960
    /*!
9961
    @brief dump escaped string
9962
9963
    Escape a string by replacing certain special characters by a sequence of an
9964
    escape character (backslash) and another character and other control
9965
    characters by a sequence of "\u" followed by a four-digit hex
9966
    representation. The escaped string is written to output stream @a o.
9967
9968
    @param[in] s  the string to escape
9969
    @param[in] ensure_ascii  whether to escape non-ASCII characters with
9970
                             \uXXXX sequences
9971
9972
    @complexity Linear in the length of string @a s.
9973
    */
9974
    void dump_escaped(const string_t& s, const bool ensure_ascii)
15.3k
9975
    {
15.3k
9976
        uint32_t codepoint;
15.3k
9977
        uint8_t state = UTF8_ACCEPT;
15.3k
9978
        std::size_t bytes = 0;  // number of bytes written to string_buffer
15.3k
9979
101k
9980
        for (std::size_t i = 0; i < s.size(); ++i)
86.0k
9981
        {
86.0k
9982
            const auto byte = static_cast<uint8_t>(s[i]);
86.0k
9983
86.0k
9984
            switch (decode(state, codepoint, byte))
86.0k
9985
            {
86.0k
9986
                case UTF8_ACCEPT:  // decode found a new code point
86.0k
9987
                {
86.0k
9988
                    switch (codepoint)
86.0k
9989
                    {
0
9990
                        case 0x08: // backspace
0
9991
                        {
0
9992
                            string_buffer[bytes++] = '\\';
0
9993
                            string_buffer[bytes++] = 'b';
0
9994
                            break;
0
9995
                        }
0
9996
0
9997
                        case 0x09: // horizontal tab
0
9998
                        {
0
9999
                            string_buffer[bytes++] = '\\';
0
10000
                            string_buffer[bytes++] = 't';
0
10001
                            break;
0
10002
                        }
0
10003
0
10004
                        case 0x0A: // newline
0
10005
                        {
0
10006
                            string_buffer[bytes++] = '\\';
0
10007
                            string_buffer[bytes++] = 'n';
0
10008
                            break;
0
10009
                        }
0
10010
0
10011
                        case 0x0C: // formfeed
0
10012
                        {
0
10013
                            string_buffer[bytes++] = '\\';
0
10014
                            string_buffer[bytes++] = 'f';
0
10015
                            break;
0
10016
                        }
0
10017
0
10018
                        case 0x0D: // carriage return
0
10019
                        {
0
10020
                            string_buffer[bytes++] = '\\';
0
10021
                            string_buffer[bytes++] = 'r';
0
10022
                            break;
0
10023
                        }
0
10024
0
10025
                        case 0x22: // quotation mark
0
10026
                        {
0
10027
                            string_buffer[bytes++] = '\\';
0
10028
                            string_buffer[bytes++] = '\"';
0
10029
                            break;
0
10030
                        }
0
10031
0
10032
                        case 0x5C: // reverse solidus
0
10033
                        {
0
10034
                            string_buffer[bytes++] = '\\';
0
10035
                            string_buffer[bytes++] = '\\';
0
10036
                            break;
0
10037
                        }
0
10038
86.0k
10039
                        default:
86.0k
10040
                        {
86.0k
10041
                            // escape control characters (0x00..0x1F) or, if
86.0k
10042
                            // ensure_ascii parameter is used, non-ASCII characters
86.0k
10043
                            if ((codepoint <= 0x1F) or (ensure_ascii and (codepoint >= 0x7F)))
0
10044
                            {
0
10045
                                if (codepoint <= 0xFFFF)
0
10046
                                {
0
10047
                                    std::snprintf(string_buffer.data() + bytes, 7, "\\u%04x",
0
10048
                                                  static_cast<uint16_t>(codepoint));
0
10049
                                    bytes += 6;
0
10050
                                }
0
10051
                                else
0
10052
                                {
0
10053
                                    std::snprintf(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
0
10054
                                                  static_cast<uint16_t>(0xD7C0 + (codepoint >> 10)),
0
10055
                                                  static_cast<uint16_t>(0xDC00 + (codepoint & 0x3FF)));
0
10056
                                    bytes += 12;
0
10057
                                }
0
10058
                            }
86.0k
10059
                            else
86.0k
10060
                            {
86.0k
10061
                                // copy byte to buffer (all previous bytes
86.0k
10062
                                // been copied have in default case above)
86.0k
10063
                                string_buffer[bytes++] = s[i];
86.0k
10064
                            }
86.0k
10065
                            break;
0
10066
                        }
86.0k
10067
                    }
86.0k
10068
86.0k
10069
                    // write buffer and reset index; there must be 13 bytes
86.0k
10070
                    // left, as this is the maximal number of bytes to be
86.0k
10071
                    // written ("\uxxxx\uxxxx\0") for one code point
86.0k
10072
                    if (string_buffer.size() - bytes < 13)
0
10073
                    {
0
10074
                        o->write_characters(string_buffer.data(), bytes);
0
10075
                        bytes = 0;
0
10076
                    }
86.0k
10077
                    break;
86.0k
10078
                }
86.0k
10079
0
10080
                case UTF8_REJECT:  // decode found invalid UTF-8 byte
0
10081
                {
0
10082
                    std::string sn(3, '\0');
0
10083
                    snprintf(&sn[0], sn.size(), "%.2X", byte);
0
10084
                    JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
86.0k
10085
                }
86.0k
10086
0
10087
                default:  // decode found yet incomplete multi-byte code point
0
10088
                {
0
10089
                    if (not ensure_ascii)
0
10090
                    {
0
10091
                        // code point will not be escaped - copy byte to buffer
0
10092
                        string_buffer[bytes++] = s[i];
0
10093
                    }
0
10094
                    break;
86.0k
10095
                }
86.0k
10096
            }
86.0k
10097
        }
15.3k
10098
15.3k
10099
        if (JSON_LIKELY(state == UTF8_ACCEPT))
15.3k
10100
        {
15.3k
10101
            // write buffer
15.3k
10102
            if (bytes > 0)
15.3k
10103
            {
15.3k
10104
                o->write_characters(string_buffer.data(), bytes);
15.3k
10105
            }
15.3k
10106
        }
15.3k
10107
        else
0
10108
        {
0
10109
            // we finish reading, but do not accept: string was incomplete
0
10110
            std::string sn(3, '\0');
0
10111
            snprintf(&sn[0], sn.size(), "%.2X", static_cast<uint8_t>(s.back()));
0
10112
            JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
0
10113
        }
15.3k
10114
    }
10115
10116
    /*!
10117
    @brief dump an integer
10118
10119
    Dump a given integer to output stream @a o. Works internally with
10120
    @a number_buffer.
10121
10122
    @param[in] x  integer number (signed or unsigned) to dump
10123
    @tparam NumberType either @a number_integer_t or @a number_unsigned_t
10124
    */
10125
    template<typename NumberType, detail::enable_if_t<
10126
                 std::is_same<NumberType, number_unsigned_t>::value or
10127
                 std::is_same<NumberType, number_integer_t>::value,
10128
                 int> = 0>
10129
    void dump_integer(NumberType x)
1.03k
10130
    {
1.03k
10131
        // special case for "0"
1.03k
10132
        if (x == 0)
44
10133
        {
44
10134
            o->write_character('0');
44
10135
            return;
44
10136
        }
1.03k
10137
992
10138
        const bool is_negative = (x <= 0) and (x != 0);  // see issue #755
992
10139
        std::size_t i = 0;
992
10140
2.80k
10141
        while (x != 0)
1.81k
10142
        {
1.81k
10143
            // spare 1 byte for '\0'
1.81k
10144
            assert(i < number_buffer.size() - 1);
1.81k
10145
1.81k
10146
            const auto digit = std::labs(static_cast<long>(x % 10));
1.81k
10147
            number_buffer[i++] = static_cast<char>('0' + digit);
1.81k
10148
            x /= 10;
1.81k
10149
        }
992
10150
992
10151
        if (is_negative)
4
10152
        {
4
10153
            // make sure there is capacity for the '-'
4
10154
            assert(i < number_buffer.size() - 2);
4
10155
            number_buffer[i++] = '-';
4
10156
        }
992
10157
992
10158
        std::reverse(number_buffer.begin(), number_buffer.begin() + i);
992
10159
        o->write_characters(number_buffer.data(), i);
992
10160
    }
_ZN8nlohmann6detail10serializerINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12dump_integerIyLi0EEEvT_
1.02k
10130
    {
1.02k
10131
        // special case for "0"
1.02k
10132
        if (x == 0)
44
10133
        {
44
10134
            o->write_character('0');
44
10135
            return;
44
10136
        }
1.02k
10137
984
10138
        const bool is_negative = (x <= 0) and (x != 0);  // see issue #755
984
10139
        std::size_t i = 0;
984
10140
2.76k
10141
        while (x != 0)
1.78k
10142
        {
1.78k
10143
            // spare 1 byte for '\0'
1.78k
10144
            assert(i < number_buffer.size() - 1);
1.78k
10145
1.78k
10146
            const auto digit = std::labs(static_cast<long>(x % 10));
1.78k
10147
            number_buffer[i++] = static_cast<char>('0' + digit);
1.78k
10148
            x /= 10;
1.78k
10149
        }
984
10150
984
10151
        if (is_negative)
0
10152
        {
0
10153
            // make sure there is capacity for the '-'
0
10154
            assert(i < number_buffer.size() - 2);
0
10155
            number_buffer[i++] = '-';
0
10156
        }
984
10157
984
10158
        std::reverse(number_buffer.begin(), number_buffer.begin() + i);
984
10159
        o->write_characters(number_buffer.data(), i);
984
10160
    }
_ZN8nlohmann6detail10serializerINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEEE12dump_integerIxLi0EEEvT_
8
10130
    {
8
10131
        // special case for "0"
8
10132
        if (x == 0)
0
10133
        {
0
10134
            o->write_character('0');
0
10135
            return;
0
10136
        }
8
10137
8
10138
        const bool is_negative = (x <= 0) and (x != 0);  // see issue #755
8
10139
        std::size_t i = 0;
8
10140
36
10141
        while (x != 0)
28
10142
        {
28
10143
            // spare 1 byte for '\0'
28
10144
            assert(i < number_buffer.size() - 1);
28
10145
28
10146
            const auto digit = std::labs(static_cast<long>(x % 10));
28
10147
            number_buffer[i++] = static_cast<char>('0' + digit);
28
10148
            x /= 10;
28
10149
        }
8
10150
8
10151
        if (is_negative)
4
10152
        {
4
10153
            // make sure there is capacity for the '-'
4
10154
            assert(i < number_buffer.size() - 2);
4
10155
            number_buffer[i++] = '-';
4
10156
        }
8
10157
8
10158
        std::reverse(number_buffer.begin(), number_buffer.begin() + i);
8
10159
        o->write_characters(number_buffer.data(), i);
8
10160
    }
10161
10162
    /*!
10163
    @brief dump a floating-point number
10164
10165
    Dump a given floating-point number to output stream @a o. Works internally
10166
    with @a number_buffer.
10167
10168
    @param[in] x  floating-point number to dump
10169
    */
10170
    void dump_float(number_float_t x)
28
10171
    {
28
10172
        // NaN / inf
28
10173
        if (not std::isfinite(x))
0
10174
        {
0
10175
            o->write_characters("null", 4);
0
10176
            return;
0
10177
        }
28
10178
28
10179
        // If number_float_t is an IEEE-754 single or double precision number,
28
10180
        // use the Grisu2 algorithm to produce short numbers which are
28
10181
        // guaranteed to round-trip, using strtof and strtod, resp.
28
10182
        //
28
10183
        // NB: The test below works if <long double> == <double>.
28
10184
        static constexpr bool is_ieee_single_or_double
0
10185
            = (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 24 and std::numeric_limits<number_float_t>::max_exponent == 128) or
0
10186
              (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 53 and std::numeric_limits<number_float_t>::max_exponent == 1024);
28
10187
28
10188
        dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
28
10189
    }
10190
10191
    void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
28
10192
    {
28
10193
        char* begin = number_buffer.data();
28
10194
        char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
28
10195
28
10196
        o->write_characters(begin, static_cast<size_t>(end - begin));
28
10197
    }
10198
10199
    void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
10200
    {
10201
        // get number of digits for a float -> text -> float round-trip
10202
        static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
10203
10204
        // the actual conversion
10205
        std::ptrdiff_t len = snprintf(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
10206
10207
        // negative value indicates an error
10208
        assert(len > 0);
10209
        // check if buffer was large enough
10210
        assert(static_cast<std::size_t>(len) < number_buffer.size());
10211
10212
        // erase thousands separator
10213
        if (thousands_sep != '\0')
10214
        {
10215
            const auto end = std::remove(number_buffer.begin(),
10216
                                         number_buffer.begin() + len, thousands_sep);
10217
            std::fill(end, number_buffer.end(), '\0');
10218
            assert((end - number_buffer.begin()) <= len);
10219
            len = (end - number_buffer.begin());
10220
        }
10221
10222
        // convert decimal point to '.'
10223
        if (decimal_point != '\0' and decimal_point != '.')
10224
        {
10225
            const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
10226
            if (dec_pos != number_buffer.end())
10227
            {
10228
                *dec_pos = '.';
10229
            }
10230
        }
10231
10232
        o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
10233
10234
        // determine if need to append ".0"
10235
        const bool value_is_int_like =
10236
            std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
10237
                         [](char c)
10238
        {
10239
            return (c == '.' or c == 'e');
10240
        });
10241
10242
        if (value_is_int_like)
10243
        {
10244
            o->write_characters(".0", 2);
10245
        }
10246
    }
10247
10248
    /*!
10249
    @brief check whether a string is UTF-8 encoded
10250
10251
    The function checks each byte of a string whether it is UTF-8 encoded. The
10252
    result of the check is stored in the @a state parameter. The function must
10253
    be called initially with state 0 (accept). State 1 means the string must
10254
    be rejected, because the current byte is not allowed. If the string is
10255
    completely processed, but the state is non-zero, the string ended
10256
    prematurely; that is, the last byte indicated more bytes should have
10257
    followed.
10258
10259
    @param[in,out] state  the state of the decoding
10260
    @param[in,out] codep  codepoint (valid only if resulting state is UTF8_ACCEPT)
10261
    @param[in] byte       next byte to decode
10262
    @return               new state
10263
10264
    @note The function has been edited: a std::array is used.
10265
10266
    @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
10267
    @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
10268
    */
10269
    static uint8_t decode(uint8_t& state, uint32_t& codep, const uint8_t byte) noexcept
86.0k
10270
    {
86.0k
10271
        static const std::array<uint8_t, 400> utf8d =
86.0k
10272
        {
86.0k
10273
            {
86.0k
10274
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
86.0k
10275
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
86.0k
10276
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
86.0k
10277
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
86.0k
10278
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
86.0k
10279
                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
86.0k
10280
                8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
86.0k
10281
                0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
86.0k
10282
                0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
86.0k
10283
                0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
86.0k
10284
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
86.0k
10285
                1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
86.0k
10286
                1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
86.0k
10287
                1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
86.0k
10288
            }
86.0k
10289
        };
86.0k
10290
86.0k
10291
        const uint8_t type = utf8d[byte];
86.0k
10292
86.0k
10293
        codep = (state != UTF8_ACCEPT)
0
10294
                ? (byte & 0x3fu) | (codep << 6)
86.0k
10295
                : static_cast<uint32_t>(0xff >> type) & (byte);
86.0k
10296
86.0k
10297
        state = utf8d[256u + state * 16u + type];
86.0k
10298
        return state;
86.0k
10299
    }
10300
10301
  private:
10302
    /// the output of the serializer
10303
    output_adapter_t<char> o = nullptr;
10304
10305
    /// a (hopefully) large enough character buffer
10306
    std::array<char, 64> number_buffer{{}};
10307
10308
    /// the locale
10309
    const std::lconv* loc = nullptr;
10310
    /// the locale's thousand separator character
10311
    const char thousands_sep = '\0';
10312
    /// the locale's decimal point character
10313
    const char decimal_point = '\0';
10314
10315
    /// string buffer
10316
    std::array<char, 512> string_buffer{{}};
10317
10318
    /// the indentation character
10319
    const char indent_char;
10320
    /// the indentation string
10321
    string_t indent_string;
10322
};
10323
}
10324
}
10325
10326
// #include <nlohmann/detail/json_ref.hpp>
10327
10328
10329
#include <initializer_list>
10330
#include <utility>
10331
10332
namespace nlohmann
10333
{
10334
namespace detail
10335
{
10336
template<typename BasicJsonType>
10337
class json_ref
10338
{
10339
  public:
10340
    using value_type = BasicJsonType;
10341
10342
    json_ref(value_type&& value)
10343
        : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
10344
    {}
10345
10346
    json_ref(const value_type& value)
10347
        : value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
10348
    {}
10349
10350
    json_ref(std::initializer_list<json_ref> init)
10351
        : owned_value(init), value_ref(&owned_value), is_rvalue(true)
10352
    {}
10353
10354
    template<class... Args>
10355
    json_ref(Args&& ... args)
10356
        : owned_value(std::forward<Args>(args)...), value_ref(&owned_value), is_rvalue(true)
10357
    {}
10358
10359
    // class should be movable only
10360
    json_ref(json_ref&&) = default;
10361
    json_ref(const json_ref&) = delete;
10362
    json_ref& operator=(const json_ref&) = delete;
10363
10364
    value_type moved_or_copied() const
10365
    {
10366
        if (is_rvalue)
10367
        {
10368
            return std::move(*value_ref);
10369
        }
10370
        return *value_ref;
10371
    }
10372
10373
    value_type const& operator*() const
10374
    {
10375
        return *static_cast<value_type const*>(value_ref);
10376
    }
10377
10378
    value_type const* operator->() const
10379
    {
10380
        return static_cast<value_type const*>(value_ref);
10381
    }
10382
10383
  private:
10384
    mutable value_type owned_value = nullptr;
10385
    value_type* value_ref = nullptr;
10386
    const bool is_rvalue;
10387
};
10388
}
10389
}
10390
10391
// #include <nlohmann/detail/json_pointer.hpp>
10392
10393
10394
#include <cassert> // assert
10395
#include <numeric> // accumulate
10396
#include <string> // string
10397
#include <vector> // vector
10398
10399
// #include <nlohmann/detail/macro_scope.hpp>
10400
10401
// #include <nlohmann/detail/exceptions.hpp>
10402
10403
// #include <nlohmann/detail/value_t.hpp>
10404
10405
10406
namespace nlohmann
10407
{
10408
template<typename BasicJsonType>
10409
class json_pointer
10410
{
10411
    // allow basic_json to access private members
10412
    NLOHMANN_BASIC_JSON_TPL_DECLARATION
10413
    friend class basic_json;
10414
10415
  public:
10416
    /*!
10417
    @brief create JSON pointer
10418
10419
    Create a JSON pointer according to the syntax described in
10420
    [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).
10421
10422
    @param[in] s  string representing the JSON pointer; if omitted, the empty
10423
                  string is assumed which references the whole JSON value
10424
10425
    @throw parse_error.107 if the given JSON pointer @a s is nonempty and does
10426
                           not begin with a slash (`/`); see example below
10427
10428
    @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is
10429
    not followed by `0` (representing `~`) or `1` (representing `/`); see
10430
    example below
10431
10432
    @liveexample{The example shows the construction several valid JSON pointers
10433
    as well as the exceptional behavior.,json_pointer}
10434
10435
    @since version 2.0.0
10436
    */
10437
    explicit json_pointer(const std::string& s = "")
10438
        : reference_tokens(split(s))
10439
    {}
10440
10441
    /*!
10442
    @brief return a string representation of the JSON pointer
10443
10444
    @invariant For each JSON pointer `ptr`, it holds:
10445
    @code {.cpp}
10446
    ptr == json_pointer(ptr.to_string());
10447
    @endcode
10448
10449
    @return a string representation of the JSON pointer
10450
10451
    @liveexample{The example shows the result of `to_string`.,
10452
    json_pointer__to_string}
10453
10454
    @since version 2.0.0
10455
    */
10456
    std::string to_string() const noexcept
10457
    {
10458
        return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
10459
                               std::string{},
10460
                               [](const std::string & a, const std::string & b)
10461
        {
10462
            return a + "/" + escape(b);
10463
        });
10464
    }
10465
10466
    /// @copydoc to_string()
10467
    operator std::string() const
10468
    {
10469
        return to_string();
10470
    }
10471
10472
    /*!
10473
    @param[in] s  reference token to be converted into an array index
10474
10475
    @return integer representation of @a s
10476
10477
    @throw out_of_range.404 if string @a s could not be converted to an integer
10478
    */
10479
    static int array_index(const std::string& s)
10480
    {
10481
        std::size_t processed_chars = 0;
10482
        const int res = std::stoi(s, &processed_chars);
10483
10484
        // check if the string was completely read
10485
        if (JSON_UNLIKELY(processed_chars != s.size()))
10486
        {
10487
            JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
10488
        }
10489
10490
        return res;
10491
    }
10492
10493
  private:
10494
    /*!
10495
    @brief remove and return last reference pointer
10496
    @throw out_of_range.405 if JSON pointer has no parent
10497
    */
10498
    std::string pop_back()
10499
    {
10500
        if (JSON_UNLIKELY(is_root()))
10501
        {
10502
            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
10503
        }
10504
10505
        auto last = reference_tokens.back();
10506
        reference_tokens.pop_back();
10507
        return last;
10508
    }
10509
10510
    /// return whether pointer points to the root document
10511
    bool is_root() const
10512
    {
10513
        return reference_tokens.empty();
10514
    }
10515
10516
    json_pointer top() const
10517
    {
10518
        if (JSON_UNLIKELY(is_root()))
10519
        {
10520
            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
10521
        }
10522
10523
        json_pointer result = *this;
10524
        result.reference_tokens = {reference_tokens[0]};
10525
        return result;
10526
    }
10527
10528
    /*!
10529
    @brief create and return a reference to the pointed to value
10530
10531
    @complexity Linear in the number of reference tokens.
10532
10533
    @throw parse_error.109 if array index is not a number
10534
    @throw type_error.313 if value cannot be unflattened
10535
    */
10536
    BasicJsonType& get_and_create(BasicJsonType& j) const
10537
    {
10538
        using size_type = typename BasicJsonType::size_type;
10539
        auto result = &j;
10540
10541
        // in case no reference tokens exist, return a reference to the JSON value
10542
        // j which will be overwritten by a primitive value
10543
        for (const auto& reference_token : reference_tokens)
10544
        {
10545
            switch (result->m_type)
10546
            {
10547
                case detail::value_t::null:
10548
                {
10549
                    if (reference_token == "0")
10550
                    {
10551
                        // start a new array if reference token is 0
10552
                        result = &result->operator[](0);
10553
                    }
10554
                    else
10555
                    {
10556
                        // start a new object otherwise
10557
                        result = &result->operator[](reference_token);
10558
                    }
10559
                    break;
10560
                }
10561
10562
                case detail::value_t::object:
10563
                {
10564
                    // create an entry in the object
10565
                    result = &result->operator[](reference_token);
10566
                    break;
10567
                }
10568
10569
                case detail::value_t::array:
10570
                {
10571
                    // create an entry in the array
10572
                    JSON_TRY
10573
                    {
10574
                        result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
10575
                    }
10576
                    JSON_CATCH(std::invalid_argument&)
10577
                    {
10578
                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10579
                    }
10580
                    break;
10581
                }
10582
10583
                /*
10584
                The following code is only reached if there exists a reference
10585
                token _and_ the current value is primitive. In this case, we have
10586
                an error situation, because primitive values may only occur as
10587
                single value; that is, with an empty list of reference tokens.
10588
                */
10589
                default:
10590
                    JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
10591
            }
10592
        }
10593
10594
        return *result;
10595
    }
10596
10597
    /*!
10598
    @brief return a reference to the pointed to value
10599
10600
    @note This version does not throw if a value is not present, but tries to
10601
          create nested values instead. For instance, calling this function
10602
          with pointer `"/this/that"` on a null value is equivalent to calling
10603
          `operator[]("this").operator[]("that")` on that value, effectively
10604
          changing the null value to an object.
10605
10606
    @param[in] ptr  a JSON value
10607
10608
    @return reference to the JSON value pointed to by the JSON pointer
10609
10610
    @complexity Linear in the length of the JSON pointer.
10611
10612
    @throw parse_error.106   if an array index begins with '0'
10613
    @throw parse_error.109   if an array index was not a number
10614
    @throw out_of_range.404  if the JSON pointer can not be resolved
10615
    */
10616
    BasicJsonType& get_unchecked(BasicJsonType* ptr) const
10617
    {
10618
        using size_type = typename BasicJsonType::size_type;
10619
        for (const auto& reference_token : reference_tokens)
10620
        {
10621
            // convert null values to arrays or objects before continuing
10622
            if (ptr->m_type == detail::value_t::null)
10623
            {
10624
                // check if reference token is a number
10625
                const bool nums =
10626
                    std::all_of(reference_token.begin(), reference_token.end(),
10627
                                [](const char x)
10628
                {
10629
                    return (x >= '0' and x <= '9');
10630
                });
10631
10632
                // change value to array for numbers or "-" or to object otherwise
10633
                *ptr = (nums or reference_token == "-")
10634
                       ? detail::value_t::array
10635
                       : detail::value_t::object;
10636
            }
10637
10638
            switch (ptr->m_type)
10639
            {
10640
                case detail::value_t::object:
10641
                {
10642
                    // use unchecked object access
10643
                    ptr = &ptr->operator[](reference_token);
10644
                    break;
10645
                }
10646
10647
                case detail::value_t::array:
10648
                {
10649
                    // error condition (cf. RFC 6901, Sect. 4)
10650
                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10651
                    {
10652
                        JSON_THROW(detail::parse_error::create(106, 0,
10653
                                                               "array index '" + reference_token +
10654
                                                               "' must not begin with '0'"));
10655
                    }
10656
10657
                    if (reference_token == "-")
10658
                    {
10659
                        // explicitly treat "-" as index beyond the end
10660
                        ptr = &ptr->operator[](ptr->m_value.array->size());
10661
                    }
10662
                    else
10663
                    {
10664
                        // convert array index to number; unchecked access
10665
                        JSON_TRY
10666
                        {
10667
                            ptr = &ptr->operator[](
10668
                                static_cast<size_type>(array_index(reference_token)));
10669
                        }
10670
                        JSON_CATCH(std::invalid_argument&)
10671
                        {
10672
                            JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10673
                        }
10674
                    }
10675
                    break;
10676
                }
10677
10678
                default:
10679
                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10680
            }
10681
        }
10682
10683
        return *ptr;
10684
    }
10685
10686
    /*!
10687
    @throw parse_error.106   if an array index begins with '0'
10688
    @throw parse_error.109   if an array index was not a number
10689
    @throw out_of_range.402  if the array index '-' is used
10690
    @throw out_of_range.404  if the JSON pointer can not be resolved
10691
    */
10692
    BasicJsonType& get_checked(BasicJsonType* ptr) const
10693
    {
10694
        using size_type = typename BasicJsonType::size_type;
10695
        for (const auto& reference_token : reference_tokens)
10696
        {
10697
            switch (ptr->m_type)
10698
            {
10699
                case detail::value_t::object:
10700
                {
10701
                    // note: at performs range check
10702
                    ptr = &ptr->at(reference_token);
10703
                    break;
10704
                }
10705
10706
                case detail::value_t::array:
10707
                {
10708
                    if (JSON_UNLIKELY(reference_token == "-"))
10709
                    {
10710
                        // "-" always fails the range check
10711
                        JSON_THROW(detail::out_of_range::create(402,
10712
                                                                "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
10713
                                                                ") is out of range"));
10714
                    }
10715
10716
                    // error condition (cf. RFC 6901, Sect. 4)
10717
                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10718
                    {
10719
                        JSON_THROW(detail::parse_error::create(106, 0,
10720
                                                               "array index '" + reference_token +
10721
                                                               "' must not begin with '0'"));
10722
                    }
10723
10724
                    // note: at performs range check
10725
                    JSON_TRY
10726
                    {
10727
                        ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
10728
                    }
10729
                    JSON_CATCH(std::invalid_argument&)
10730
                    {
10731
                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10732
                    }
10733
                    break;
10734
                }
10735
10736
                default:
10737
                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10738
            }
10739
        }
10740
10741
        return *ptr;
10742
    }
10743
10744
    /*!
10745
    @brief return a const reference to the pointed to value
10746
10747
    @param[in] ptr  a JSON value
10748
10749
    @return const reference to the JSON value pointed to by the JSON
10750
    pointer
10751
10752
    @throw parse_error.106   if an array index begins with '0'
10753
    @throw parse_error.109   if an array index was not a number
10754
    @throw out_of_range.402  if the array index '-' is used
10755
    @throw out_of_range.404  if the JSON pointer can not be resolved
10756
    */
10757
    const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
10758
    {
10759
        using size_type = typename BasicJsonType::size_type;
10760
        for (const auto& reference_token : reference_tokens)
10761
        {
10762
            switch (ptr->m_type)
10763
            {
10764
                case detail::value_t::object:
10765
                {
10766
                    // use unchecked object access
10767
                    ptr = &ptr->operator[](reference_token);
10768
                    break;
10769
                }
10770
10771
                case detail::value_t::array:
10772
                {
10773
                    if (JSON_UNLIKELY(reference_token == "-"))
10774
                    {
10775
                        // "-" cannot be used for const access
10776
                        JSON_THROW(detail::out_of_range::create(402,
10777
                                                                "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
10778
                                                                ") is out of range"));
10779
                    }
10780
10781
                    // error condition (cf. RFC 6901, Sect. 4)
10782
                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10783
                    {
10784
                        JSON_THROW(detail::parse_error::create(106, 0,
10785
                                                               "array index '" + reference_token +
10786
                                                               "' must not begin with '0'"));
10787
                    }
10788
10789
                    // use unchecked array access
10790
                    JSON_TRY
10791
                    {
10792
                        ptr = &ptr->operator[](
10793
                            static_cast<size_type>(array_index(reference_token)));
10794
                    }
10795
                    JSON_CATCH(std::invalid_argument&)
10796
                    {
10797
                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10798
                    }
10799
                    break;
10800
                }
10801
10802
                default:
10803
                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10804
            }
10805
        }
10806
10807
        return *ptr;
10808
    }
10809
10810
    /*!
10811
    @throw parse_error.106   if an array index begins with '0'
10812
    @throw parse_error.109   if an array index was not a number
10813
    @throw out_of_range.402  if the array index '-' is used
10814
    @throw out_of_range.404  if the JSON pointer can not be resolved
10815
    */
10816
    const BasicJsonType& get_checked(const BasicJsonType* ptr) const
10817
    {
10818
        using size_type = typename BasicJsonType::size_type;
10819
        for (const auto& reference_token : reference_tokens)
10820
        {
10821
            switch (ptr->m_type)
10822
            {
10823
                case detail::value_t::object:
10824
                {
10825
                    // note: at performs range check
10826
                    ptr = &ptr->at(reference_token);
10827
                    break;
10828
                }
10829
10830
                case detail::value_t::array:
10831
                {
10832
                    if (JSON_UNLIKELY(reference_token == "-"))
10833
                    {
10834
                        // "-" always fails the range check
10835
                        JSON_THROW(detail::out_of_range::create(402,
10836
                                                                "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
10837
                                                                ") is out of range"));
10838
                    }
10839
10840
                    // error condition (cf. RFC 6901, Sect. 4)
10841
                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10842
                    {
10843
                        JSON_THROW(detail::parse_error::create(106, 0,
10844
                                                               "array index '" + reference_token +
10845
                                                               "' must not begin with '0'"));
10846
                    }
10847
10848
                    // note: at performs range check
10849
                    JSON_TRY
10850
                    {
10851
                        ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
10852
                    }
10853
                    JSON_CATCH(std::invalid_argument&)
10854
                    {
10855
                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10856
                    }
10857
                    break;
10858
                }
10859
10860
                default:
10861
                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10862
            }
10863
        }
10864
10865
        return *ptr;
10866
    }
10867
10868
    /*!
10869
    @brief split the string input to reference tokens
10870
10871
    @note This function is only called by the json_pointer constructor.
10872
          All exceptions below are documented there.
10873
10874
    @throw parse_error.107  if the pointer is not empty or begins with '/'
10875
    @throw parse_error.108  if character '~' is not followed by '0' or '1'
10876
    */
10877
    static std::vector<std::string> split(const std::string& reference_string)
0
10878
    {
0
10879
        std::vector<std::string> result;
0
10880
0
10881
        // special case: empty reference string -> no reference tokens
0
10882
        if (reference_string.empty())
0
10883
        {
0
10884
            return result;
0
10885
        }
0
10886
0
10887
        // check if nonempty reference string begins with slash
0
10888
        if (JSON_UNLIKELY(reference_string[0] != '/'))
0
10889
        {
0
10890
            JSON_THROW(detail::parse_error::create(107, 1,
0
10891
                                                   "JSON pointer must be empty or begin with '/' - was: '" +
0
10892
                                                   reference_string + "'"));
0
10893
        }
0
10894
0
10895
        // extract the reference tokens:
0
10896
        // - slash: position of the last read slash (or end of string)
0
10897
        // - start: position after the previous slash
0
10898
        for (
0
10899
            // search for the first slash after the first character
0
10900
            std::size_t slash = reference_string.find_first_of('/', 1),
0
10901
            // set the beginning of the first reference token
0
10902
            start = 1;
0
10903
            // we can stop if start == string::npos+1 = 0
0
10904
            start != 0;
0
10905
            // set the beginning of the next reference token
0
10906
            // (will eventually be 0 if slash == std::string::npos)
0
10907
            start = slash + 1,
0
10908
            // find next slash
0
10909
            slash = reference_string.find_first_of('/', start))
0
10910
        {
0
10911
            // use the text between the beginning of the reference token
0
10912
            // (start) and the last slash (slash).
0
10913
            auto reference_token = reference_string.substr(start, slash - start);
0
10914
0
10915
            // check reference tokens are properly escaped
0
10916
            for (std::size_t pos = reference_token.find_first_of('~');
0
10917
                    pos != std::string::npos;
0
10918
                    pos = reference_token.find_first_of('~', pos + 1))
0
10919
            {
0
10920
                assert(reference_token[pos] == '~');
0
10921
0
10922
                // ~ must be followed by 0 or 1
0
10923
                if (JSON_UNLIKELY(pos == reference_token.size() - 1 or
0
10924
                                  (reference_token[pos + 1] != '0' and
0
10925
                                   reference_token[pos + 1] != '1')))
0
10926
                {
0
10927
                    JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
0
10928
                }
0
10929
            }
0
10930
0
10931
            // finally, store the reference token
0
10932
            unescape(reference_token);
0
10933
            result.push_back(reference_token);
0
10934
        }
0
10935
0
10936
        return result;
0
10937
    }
10938
10939
    /*!
10940
    @brief replace all occurrences of a substring by another string
10941
10942
    @param[in,out] s  the string to manipulate; changed so that all
10943
                   occurrences of @a f are replaced with @a t
10944
    @param[in]     f  the substring to replace with @a t
10945
    @param[in]     t  the string to replace @a f
10946
10947
    @pre The search string @a f must not be empty. **This precondition is
10948
    enforced with an assertion.**
10949
10950
    @since version 2.0.0
10951
    */
10952
    static void replace_substring(std::string& s, const std::string& f,
10953
                                  const std::string& t)
0
10954
    {
0
10955
        assert(not f.empty());
0
10956
        for (auto pos = s.find(f);                // find first occurrence of f
0
10957
                pos != std::string::npos;         // make sure f was found
0
10958
                s.replace(pos, f.size(), t),      // replace with t, and
0
10959
                pos = s.find(f, pos + t.size()))  // find next occurrence of f
0
10960
        {}
0
10961
    }
10962
10963
    /// escape "~"" to "~0" and "/" to "~1"
10964
    static std::string escape(std::string s)
10965
    {
10966
        replace_substring(s, "~", "~0");
10967
        replace_substring(s, "/", "~1");
10968
        return s;
10969
    }
10970
10971
    /// unescape "~1" to tilde and "~0" to slash (order is important!)
10972
    static void unescape(std::string& s)
0
10973
    {
0
10974
        replace_substring(s, "~1", "/");
0
10975
        replace_substring(s, "~0", "~");
0
10976
    }
10977
10978
    /*!
10979
    @param[in] reference_string  the reference string to the current value
10980
    @param[in] value             the value to consider
10981
    @param[in,out] result        the result object to insert values to
10982
10983
    @note Empty objects or arrays are flattened to `null`.
10984
    */
10985
    static void flatten(const std::string& reference_string,
10986
                        const BasicJsonType& value,
10987
                        BasicJsonType& result)
10988
    {
10989
        switch (value.m_type)
10990
        {
10991
            case detail::value_t::array:
10992
            {
10993
                if (value.m_value.array->empty())
10994
                {
10995
                    // flatten empty array as null
10996
                    result[reference_string] = nullptr;
10997
                }
10998
                else
10999
                {
11000
                    // iterate array and use index as reference string
11001
                    for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
11002
                    {
11003
                        flatten(reference_string + "/" + std::to_string(i),
11004
                                value.m_value.array->operator[](i), result);
11005
                    }
11006
                }
11007
                break;
11008
            }
11009
11010
            case detail::value_t::object:
11011
            {
11012
                if (value.m_value.object->empty())
11013
                {
11014
                    // flatten empty object as null
11015
                    result[reference_string] = nullptr;
11016
                }
11017
                else
11018
                {
11019
                    // iterate object and use keys as reference string
11020
                    for (const auto& element : *value.m_value.object)
11021
                    {
11022
                        flatten(reference_string + "/" + escape(element.first), element.second, result);
11023
                    }
11024
                }
11025
                break;
11026
            }
11027
11028
            default:
11029
            {
11030
                // add primitive value with its reference string
11031
                result[reference_string] = value;
11032
                break;
11033
            }
11034
        }
11035
    }
11036
11037
    /*!
11038
    @param[in] value  flattened JSON
11039
11040
    @return unflattened JSON
11041
11042
    @throw parse_error.109 if array index is not a number
11043
    @throw type_error.314  if value is not an object
11044
    @throw type_error.315  if object values are not primitive
11045
    @throw type_error.313  if value cannot be unflattened
11046
    */
11047
    static BasicJsonType
11048
    unflatten(const BasicJsonType& value)
11049
    {
11050
        if (JSON_UNLIKELY(not value.is_object()))
11051
        {
11052
            JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
11053
        }
11054
11055
        BasicJsonType result;
11056
11057
        // iterate the JSON object values
11058
        for (const auto& element : *value.m_value.object)
11059
        {
11060
            if (JSON_UNLIKELY(not element.second.is_primitive()))
11061
            {
11062
                JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
11063
            }
11064
11065
            // assign value to reference pointed to by JSON pointer; Note that if
11066
            // the JSON pointer is "" (i.e., points to the whole value), function
11067
            // get_and_create returns a reference to result itself. An assignment
11068
            // will then create a primitive value.
11069
            json_pointer(element.first).get_and_create(result) = element.second;
11070
        }
11071
11072
        return result;
11073
    }
11074
11075
    friend bool operator==(json_pointer const& lhs,
11076
                           json_pointer const& rhs) noexcept
11077
    {
11078
        return (lhs.reference_tokens == rhs.reference_tokens);
11079
    }
11080
11081
    friend bool operator!=(json_pointer const& lhs,
11082
                           json_pointer const& rhs) noexcept
11083
    {
11084
        return not (lhs == rhs);
11085
    }
11086
11087
    /// the reference tokens
11088
    std::vector<std::string> reference_tokens;
11089
};
11090
}
11091
11092
// #include <nlohmann/adl_serializer.hpp>
11093
11094
11095
#include <utility>
11096
11097
// #include <nlohmann/detail/conversions/from_json.hpp>
11098
11099
// #include <nlohmann/detail/conversions/to_json.hpp>
11100
11101
11102
namespace nlohmann
11103
{
11104
template<typename, typename>
11105
struct adl_serializer
11106
{
11107
    /*!
11108
    @brief convert a JSON value to any value type
11109
11110
    This function is usually called by the `get()` function of the
11111
    @ref basic_json class (either explicit or via conversion operators).
11112
11113
    @param[in] j         JSON value to read from
11114
    @param[in,out] val  value to write to
11115
    */
11116
    template<typename BasicJsonType, typename ValueType>
11117
    static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
11118
        noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val))) -> decltype(
11119
            ::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void()
11120
        )
32.4k
11121
    {
32.4k
11122
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
32.4k
11123
    }
_ZN8nlohmann14adl_serializerIbvE9from_jsonIRKNS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaS0_EEbEEDTcmclL_ZNS_12_GLOBAL__N_19from_jsonEEclsr3stdE7forwardIT_Efp_Efp0_Ecvv_EEOSG_RT0_
8
11121
    {
8
11122
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
8
11123
    }
_ZN8nlohmann14adl_serializerINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvE9from_jsonIRKNS_10basic_jsonISt3mapSt6vectorS6_bxydSaS0_EES6_EEDTcmclL_ZNS_12_GLOBAL__N_19from_jsonEEclsr3stdE7forwardIT_Efp_Efp0_Ecvv_EEOSG_RT0_
31.2k
11121
    {
31.2k
11122
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
31.2k
11123
    }
_ZN8nlohmann14adl_serializerIivE9from_jsonIRKNS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaS0_EEiEEDTcmclL_ZNS_12_GLOBAL__N_19from_jsonEEclsr3stdE7forwardIT_Efp_Efp0_Ecvv_EEOSG_RT0_
608
11121
    {
608
11122
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
608
11123
    }
_ZN8nlohmann14adl_serializerIdvE9from_jsonIRKNS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaS0_EEdEEDTcmclL_ZNS_12_GLOBAL__N_19from_jsonEEclsr3stdE7forwardIT_Efp_Efp0_Ecvv_EEOSG_RT0_
592
11121
    {
592
11122
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
592
11123
    }
11124
11125
    /*!
11126
    @brief convert any value type to a JSON value
11127
11128
    This function is usually called by the constructors of the @ref basic_json
11129
    class.
11130
11131
    @param[in,out] j  JSON value to write to
11132
    @param[in] val     value to read from
11133
    */
11134
    template <typename BasicJsonType, typename ValueType>
11135
    static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
11136
        noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
11137
    -> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)),
11138
                void())
573k
11139
    {
573k
11140
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
573k
11141
    }
_ZN8nlohmann14adl_serializerINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvE7to_jsonINS_10basic_jsonISt3mapSt6vectorS6_bxydSaS0_EES6_EEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
1.47k
11139
    {
1.47k
11140
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
1.47k
11141
    }
_ZN8nlohmann14adl_serializerIA474_cvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaS0_EERA474_KcEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSI_
548
11139
    {
548
11140
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
548
11141
    }
_ZN8nlohmann14adl_serializerIxvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaS0_EERxEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
25.3k
11139
    {
25.3k
11140
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
25.3k
11141
    }
_ZN8nlohmann14adl_serializerIdvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaS0_EERdEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
158k
11139
    {
158k
11140
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
158k
11141
    }
_ZN8nlohmann14adl_serializerIyvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaS0_EERyEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
212k
11139
    {
212k
11140
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
212k
11141
    }
_ZN8nlohmann14adl_serializerIbvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaS0_EERbEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
1.66k
11139
    {
1.66k
11140
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
1.66k
11141
    }
_ZN8nlohmann14adl_serializerINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvE7to_jsonINS_10basic_jsonISt3mapSt6vectorS6_bxydSaS0_EERS6_EEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
172k
11139
    {
172k
11140
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
172k
11141
    }
_ZN8nlohmann14adl_serializerINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvE7to_jsonINS_10basic_jsonISt3mapSt6vectorS6_bxydSaS0_EEKS6_EEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
164
11139
    {
164
11140
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
164
11141
    }
_ZN8nlohmann14adl_serializerIivE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaS0_EEiEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
4
11139
    {
4
11140
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
4
11141
    }
_ZN8nlohmann14adl_serializerIA6_cvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaS0_EERA6_KcEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSI_
4
11139
    {
4
11140
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
4
11141
    }
_ZN8nlohmann14adl_serializerIdvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaS0_EEdEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
4
11139
    {
4
11140
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
4
11141
    }
_ZN8nlohmann14adl_serializerIbvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaS0_EEbEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
4
11139
    {
4
11140
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
4
11141
    }
_ZN8nlohmann14adl_serializerIPKcvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaS0_EERKS2_EEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSI_
40
11139
    {
40
11140
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
40
11141
    }
_ZN8nlohmann14adl_serializerIjvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaS0_EERjEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
492
11139
    {
492
11140
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
492
11141
    }
11142
};
11143
}
11144
11145
11146
/*!
11147
@brief namespace for Niels Lohmann
11148
@see https://github.com/nlohmann
11149
@since version 1.0.0
11150
*/
11151
namespace nlohmann
11152
{
11153
11154
/*!
11155
@brief a class to store JSON values
11156
11157
@tparam ObjectType type for JSON objects (`std::map` by default; will be used
11158
in @ref object_t)
11159
@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used
11160
in @ref array_t)
11161
@tparam StringType type for JSON strings and object keys (`std::string` by
11162
default; will be used in @ref string_t)
11163
@tparam BooleanType type for JSON booleans (`bool` by default; will be used
11164
in @ref boolean_t)
11165
@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by
11166
default; will be used in @ref number_integer_t)
11167
@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c
11168
`uint64_t` by default; will be used in @ref number_unsigned_t)
11169
@tparam NumberFloatType type for JSON floating-point numbers (`double` by
11170
default; will be used in @ref number_float_t)
11171
@tparam AllocatorType type of the allocator to use (`std::allocator` by
11172
default)
11173
@tparam JSONSerializer the serializer to resolve internal calls to `to_json()`
11174
and `from_json()` (@ref adl_serializer by default)
11175
11176
@requirement The class satisfies the following concept requirements:
11177
- Basic
11178
 - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible):
11179
   JSON values can be default constructed. The result will be a JSON null
11180
   value.
11181
 - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible):
11182
   A JSON value can be constructed from an rvalue argument.
11183
 - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible):
11184
   A JSON value can be copy-constructed from an lvalue expression.
11185
 - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable):
11186
   A JSON value van be assigned from an rvalue argument.
11187
 - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable):
11188
   A JSON value can be copy-assigned from an lvalue expression.
11189
 - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible):
11190
   JSON values can be destructed.
11191
- Layout
11192
 - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType):
11193
   JSON values have
11194
   [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
11195
   All non-static data members are private and standard layout types, the
11196
   class has no virtual functions or (virtual) base classes.
11197
- Library-wide
11198
 - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable):
11199
   JSON values can be compared with `==`, see @ref
11200
   operator==(const_reference,const_reference).
11201
 - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable):
11202
   JSON values can be compared with `<`, see @ref
11203
   operator<(const_reference,const_reference).
11204
 - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable):
11205
   Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
11206
   other compatible types, using unqualified function call @ref swap().
11207
 - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer):
11208
   JSON values can be compared against `std::nullptr_t` objects which are used
11209
   to model the `null` value.
11210
- Container
11211
 - [Container](https://en.cppreference.com/w/cpp/named_req/Container):
11212
   JSON values can be used like STL containers and provide iterator access.
11213
 - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer);
11214
   JSON values can be used like STL containers and provide reverse iterator
11215
   access.
11216
11217
@invariant The member variables @a m_value and @a m_type have the following
11218
relationship:
11219
- If `m_type == value_t::object`, then `m_value.object != nullptr`.
11220
- If `m_type == value_t::array`, then `m_value.array != nullptr`.
11221
- If `m_type == value_t::string`, then `m_value.string != nullptr`.
11222
The invariants are checked by member function assert_invariant().
11223
11224
@internal
11225
@note ObjectType trick from http://stackoverflow.com/a/9860911
11226
@endinternal
11227
11228
@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange
11229
Format](http://rfc7159.net/rfc7159)
11230
11231
@since version 1.0.0
11232
11233
@nosubgrouping
11234
*/
11235
NLOHMANN_BASIC_JSON_TPL_DECLARATION
11236
class basic_json
11237
{
11238
  private:
11239
    template<detail::value_t> friend struct detail::external_constructor;
11240
    friend ::nlohmann::json_pointer<basic_json>;
11241
    friend ::nlohmann::detail::parser<basic_json>;
11242
    friend ::nlohmann::detail::serializer<basic_json>;
11243
    template<typename BasicJsonType>
11244
    friend class ::nlohmann::detail::iter_impl;
11245
    template<typename BasicJsonType, typename CharType>
11246
    friend class ::nlohmann::detail::binary_writer;
11247
    template<typename BasicJsonType, typename SAX>
11248
    friend class ::nlohmann::detail::binary_reader;
11249
    template<typename BasicJsonType>
11250
    friend class ::nlohmann::detail::json_sax_dom_parser;
11251
    template<typename BasicJsonType>
11252
    friend class ::nlohmann::detail::json_sax_dom_callback_parser;
11253
11254
    /// workaround type for MSVC
11255
    using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
11256
11257
    // convenience aliases for types residing in namespace detail;
11258
    using lexer = ::nlohmann::detail::lexer<basic_json>;
11259
    using parser = ::nlohmann::detail::parser<basic_json>;
11260
11261
    using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
11262
    template<typename BasicJsonType>
11263
    using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
11264
    template<typename BasicJsonType>
11265
    using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
11266
    template<typename Iterator>
11267
    using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
11268
    template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
11269
11270
    template<typename CharType>
11271
    using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
11272
11273
    using binary_reader = ::nlohmann::detail::binary_reader<basic_json>;
11274
    template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
11275
11276
    using serializer = ::nlohmann::detail::serializer<basic_json>;
11277
11278
  public:
11279
    using value_t = detail::value_t;
11280
    /// JSON Pointer, see @ref nlohmann::json_pointer
11281
    using json_pointer = ::nlohmann::json_pointer<basic_json>;
11282
    template<typename T, typename SFINAE>
11283
    using json_serializer = JSONSerializer<T, SFINAE>;
11284
    /// helper type for initializer lists of basic_json values
11285
    using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
11286
11287
    using input_format_t = detail::input_format_t;
11288
    /// SAX interface type, see @ref nlohmann::json_sax
11289
    using json_sax_t = json_sax<basic_json>;
11290
11291
    ////////////////
11292
    // exceptions //
11293
    ////////////////
11294
11295
    /// @name exceptions
11296
    /// Classes to implement user-defined exceptions.
11297
    /// @{
11298
11299
    /// @copydoc detail::exception
11300
    using exception = detail::exception;
11301
    /// @copydoc detail::parse_error
11302
    using parse_error = detail::parse_error;
11303
    /// @copydoc detail::invalid_iterator
11304
    using invalid_iterator = detail::invalid_iterator;
11305
    /// @copydoc detail::type_error
11306
    using type_error = detail::type_error;
11307
    /// @copydoc detail::out_of_range
11308
    using out_of_range = detail::out_of_range;
11309
    /// @copydoc detail::other_error
11310
    using other_error = detail::other_error;
11311
11312
    /// @}
11313
11314
11315
    /////////////////////
11316
    // container types //
11317
    /////////////////////
11318
11319
    /// @name container types
11320
    /// The canonic container types to use @ref basic_json like any other STL
11321
    /// container.
11322
    /// @{
11323
11324
    /// the type of elements in a basic_json container
11325
    using value_type = basic_json;
11326
11327
    /// the type of an element reference
11328
    using reference = value_type&;
11329
    /// the type of an element const reference
11330
    using const_reference = const value_type&;
11331
11332
    /// a type to represent differences between iterators
11333
    using difference_type = std::ptrdiff_t;
11334
    /// a type to represent container sizes
11335
    using size_type = std::size_t;
11336
11337
    /// the allocator type
11338
    using allocator_type = AllocatorType<basic_json>;
11339
11340
    /// the type of an element pointer
11341
    using pointer = typename std::allocator_traits<allocator_type>::pointer;
11342
    /// the type of an element const pointer
11343
    using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
11344
11345
    /// an iterator for a basic_json container
11346
    using iterator = iter_impl<basic_json>;
11347
    /// a const iterator for a basic_json container
11348
    using const_iterator = iter_impl<const basic_json>;
11349
    /// a reverse iterator for a basic_json container
11350
    using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
11351
    /// a const reverse iterator for a basic_json container
11352
    using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
11353
11354
    /// @}
11355
11356
11357
    /*!
11358
    @brief returns the allocator associated with the container
11359
    */
11360
    static allocator_type get_allocator()
11361
    {
11362
        return allocator_type();
11363
    }
11364
11365
    /*!
11366
    @brief returns version information on the library
11367
11368
    This function returns a JSON object with information about the library,
11369
    including the version number and information on the platform and compiler.
11370
11371
    @return JSON object holding version information
11372
    key         | description
11373
    ----------- | ---------------
11374
    `compiler`  | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).
11375
    `copyright` | The copyright line for the library as string.
11376
    `name`      | The name of the library as string.
11377
    `platform`  | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.
11378
    `url`       | The URL of the project as string.
11379
    `version`   | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).
11380
11381
    @liveexample{The following code shows an example output of the `meta()`
11382
    function.,meta}
11383
11384
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
11385
    changes to any JSON value.
11386
11387
    @complexity Constant.
11388
11389
    @since 2.1.0
11390
    */
11391
    static basic_json meta()
11392
    {
11393
        basic_json result;
11394
11395
        result["copyright"] = "(C) 2013-2017 Niels Lohmann";
11396
        result["name"] = "JSON for Modern C++";
11397
        result["url"] = "https://github.com/nlohmann/json";
11398
        result["version"]["string"] =
11399
            std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
11400
            std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
11401
            std::to_string(NLOHMANN_JSON_VERSION_PATCH);
11402
        result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
11403
        result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
11404
        result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
11405
11406
#ifdef _WIN32
11407
        result["platform"] = "win32";
11408
#elif defined __linux__
11409
        result["platform"] = "linux";
11410
#elif defined __APPLE__
11411
        result["platform"] = "apple";
11412
#elif defined __unix__
11413
        result["platform"] = "unix";
11414
#else
11415
        result["platform"] = "unknown";
11416
#endif
11417
11418
#if defined(__ICC) || defined(__INTEL_COMPILER)
11419
        result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
11420
#elif defined(__clang__)
11421
        result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
11422
#elif defined(__GNUC__) || defined(__GNUG__)
11423
        result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
11424
#elif defined(__HP_cc) || defined(__HP_aCC)
11425
        result["compiler"] = "hp"
11426
#elif defined(__IBMCPP__)
11427
        result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
11428
#elif defined(_MSC_VER)
11429
        result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
11430
#elif defined(__PGI)
11431
        result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
11432
#elif defined(__SUNPRO_CC)
11433
        result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
11434
#else
11435
        result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
11436
#endif
11437
11438
#ifdef __cplusplus
11439
        result["compiler"]["c++"] = std::to_string(__cplusplus);
11440
#else
11441
        result["compiler"]["c++"] = "unknown";
11442
#endif
11443
        return result;
11444
    }
11445
11446
11447
    ///////////////////////////
11448
    // JSON value data types //
11449
    ///////////////////////////
11450
11451
    /// @name JSON value data types
11452
    /// The data types to store a JSON value. These types are derived from
11453
    /// the template arguments passed to class @ref basic_json.
11454
    /// @{
11455
11456
#if defined(JSON_HAS_CPP_14)
11457
    // Use transparent comparator if possible, combined with perfect forwarding
11458
    // on find() and count() calls prevents unnecessary string construction.
11459
    using object_comparator_t = std::less<>;
11460
#else
11461
    using object_comparator_t = std::less<StringType>;
11462
#endif
11463
11464
    /*!
11465
    @brief a type for an object
11466
11467
    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:
11468
    > An object is an unordered collection of zero or more name/value pairs,
11469
    > where a name is a string and a value is a string, number, boolean, null,
11470
    > object, or array.
11471
11472
    To store objects in C++, a type is defined by the template parameters
11473
    described below.
11474
11475
    @tparam ObjectType  the container to store objects (e.g., `std::map` or
11476
    `std::unordered_map`)
11477
    @tparam StringType the type of the keys or names (e.g., `std::string`).
11478
    The comparison function `std::less<StringType>` is used to order elements
11479
    inside the container.
11480
    @tparam AllocatorType the allocator to use for objects (e.g.,
11481
    `std::allocator`)
11482
11483
    #### Default type
11484
11485
    With the default values for @a ObjectType (`std::map`), @a StringType
11486
    (`std::string`), and @a AllocatorType (`std::allocator`), the default
11487
    value for @a object_t is:
11488
11489
    @code {.cpp}
11490
    std::map<
11491
      std::string, // key_type
11492
      basic_json, // value_type
11493
      std::less<std::string>, // key_compare
11494
      std::allocator<std::pair<const std::string, basic_json>> // allocator_type
11495
    >
11496
    @endcode
11497
11498
    #### Behavior
11499
11500
    The choice of @a object_t influences the behavior of the JSON class. With
11501
    the default type, objects have the following behavior:
11502
11503
    - When all names are unique, objects will be interoperable in the sense
11504
      that all software implementations receiving that object will agree on
11505
      the name-value mappings.
11506
    - When the names within an object are not unique, it is unspecified which
11507
      one of the values for a given key will be chosen. For instance,
11508
      `{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or
11509
      `{"key": 2}`.
11510
    - Internally, name/value pairs are stored in lexicographical order of the
11511
      names. Objects will also be serialized (see @ref dump) in this order.
11512
      For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored
11513
      and serialized as `{"a": 2, "b": 1}`.
11514
    - When comparing objects, the order of the name/value pairs is irrelevant.
11515
      This makes objects interoperable in the sense that they will not be
11516
      affected by these differences. For instance, `{"b": 1, "a": 2}` and
11517
      `{"a": 2, "b": 1}` will be treated as equal.
11518
11519
    #### Limits
11520
11521
    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
11522
    > An implementation may set limits on the maximum depth of nesting.
11523
11524
    In this class, the object's limit of nesting is not explicitly constrained.
11525
    However, a maximum depth of nesting may be introduced by the compiler or
11526
    runtime environment. A theoretical limit can be queried by calling the
11527
    @ref max_size function of a JSON object.
11528
11529
    #### Storage
11530
11531
    Objects are stored as pointers in a @ref basic_json type. That is, for any
11532
    access to object values, a pointer of type `object_t*` must be
11533
    dereferenced.
11534
11535
    @sa @ref array_t -- type for an array value
11536
11537
    @since version 1.0.0
11538
11539
    @note The order name/value pairs are added to the object is *not*
11540
    preserved by the library. Therefore, iterating an object may return
11541
    name/value pairs in a different order than they were originally stored. In
11542
    fact, keys will be traversed in alphabetical order as `std::map` with
11543
    `std::less` is used by default. Please note this behavior conforms to [RFC
11544
    7159](http://rfc7159.net/rfc7159), because any order implements the
11545
    specified "unordered" nature of JSON objects.
11546
    */
11547
    using object_t = ObjectType<StringType,
11548
          basic_json,
11549
          object_comparator_t,
11550
          AllocatorType<std::pair<const StringType,
11551
          basic_json>>>;
11552
11553
    /*!
11554
    @brief a type for an array
11555
11556
    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:
11557
    > An array is an ordered sequence of zero or more values.
11558
11559
    To store objects in C++, a type is defined by the template parameters
11560
    explained below.
11561
11562
    @tparam ArrayType  container type to store arrays (e.g., `std::vector` or
11563
    `std::list`)
11564
    @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)
11565
11566
    #### Default type
11567
11568
    With the default values for @a ArrayType (`std::vector`) and @a
11569
    AllocatorType (`std::allocator`), the default value for @a array_t is:
11570
11571
    @code {.cpp}
11572
    std::vector<
11573
      basic_json, // value_type
11574
      std::allocator<basic_json> // allocator_type
11575
    >
11576
    @endcode
11577
11578
    #### Limits
11579
11580
    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
11581
    > An implementation may set limits on the maximum depth of nesting.
11582
11583
    In this class, the array's limit of nesting is not explicitly constrained.
11584
    However, a maximum depth of nesting may be introduced by the compiler or
11585
    runtime environment. A theoretical limit can be queried by calling the
11586
    @ref max_size function of a JSON array.
11587
11588
    #### Storage
11589
11590
    Arrays are stored as pointers in a @ref basic_json type. That is, for any
11591
    access to array values, a pointer of type `array_t*` must be dereferenced.
11592
11593
    @sa @ref object_t -- type for an object value
11594
11595
    @since version 1.0.0
11596
    */
11597
    using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
11598
11599
    /*!
11600
    @brief a type for a string
11601
11602
    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:
11603
    > A string is a sequence of zero or more Unicode characters.
11604
11605
    To store objects in C++, a type is defined by the template parameter
11606
    described below. Unicode values are split by the JSON class into
11607
    byte-sized characters during deserialization.
11608
11609
    @tparam StringType  the container to store strings (e.g., `std::string`).
11610
    Note this container is used for keys/names in objects, see @ref object_t.
11611
11612
    #### Default type
11613
11614
    With the default values for @a StringType (`std::string`), the default
11615
    value for @a string_t is:
11616
11617
    @code {.cpp}
11618
    std::string
11619
    @endcode
11620
11621
    #### Encoding
11622
11623
    Strings are stored in UTF-8 encoding. Therefore, functions like
11624
    `std::string::size()` or `std::string::length()` return the number of
11625
    bytes in the string rather than the number of characters or glyphs.
11626
11627
    #### String comparison
11628
11629
    [RFC 7159](http://rfc7159.net/rfc7159) states:
11630
    > Software implementations are typically required to test names of object
11631
    > members for equality. Implementations that transform the textual
11632
    > representation into sequences of Unicode code units and then perform the
11633
    > comparison numerically, code unit by code unit, are interoperable in the
11634
    > sense that implementations will agree in all cases on equality or
11635
    > inequality of two strings. For example, implementations that compare
11636
    > strings with escaped characters unconverted may incorrectly find that
11637
    > `"a\\b"` and `"a\u005Cb"` are not equal.
11638
11639
    This implementation is interoperable as it does compare strings code unit
11640
    by code unit.
11641
11642
    #### Storage
11643
11644
    String values are stored as pointers in a @ref basic_json type. That is,
11645
    for any access to string values, a pointer of type `string_t*` must be
11646
    dereferenced.
11647
11648
    @since version 1.0.0
11649
    */
11650
    using string_t = StringType;
11651
11652
    /*!
11653
    @brief a type for a boolean
11654
11655
    [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a
11656
    type which differentiates the two literals `true` and `false`.
11657
11658
    To store objects in C++, a type is defined by the template parameter @a
11659
    BooleanType which chooses the type to use.
11660
11661
    #### Default type
11662
11663
    With the default values for @a BooleanType (`bool`), the default value for
11664
    @a boolean_t is:
11665
11666
    @code {.cpp}
11667
    bool
11668
    @endcode
11669
11670
    #### Storage
11671
11672
    Boolean values are stored directly inside a @ref basic_json type.
11673
11674
    @since version 1.0.0
11675
    */
11676
    using boolean_t = BooleanType;
11677
11678
    /*!
11679
    @brief a type for a number (integer)
11680
11681
    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
11682
    > The representation of numbers is similar to that used in most
11683
    > programming languages. A number is represented in base 10 using decimal
11684
    > digits. It contains an integer component that may be prefixed with an
11685
    > optional minus sign, which may be followed by a fraction part and/or an
11686
    > exponent part. Leading zeros are not allowed. (...) Numeric values that
11687
    > cannot be represented in the grammar below (such as Infinity and NaN)
11688
    > are not permitted.
11689
11690
    This description includes both integer and floating-point numbers.
11691
    However, C++ allows more precise storage if it is known whether the number
11692
    is a signed integer, an unsigned integer or a floating-point number.
11693
    Therefore, three different types, @ref number_integer_t, @ref
11694
    number_unsigned_t and @ref number_float_t are used.
11695
11696
    To store integer numbers in C++, a type is defined by the template
11697
    parameter @a NumberIntegerType which chooses the type to use.
11698
11699
    #### Default type
11700
11701
    With the default values for @a NumberIntegerType (`int64_t`), the default
11702
    value for @a number_integer_t is:
11703
11704
    @code {.cpp}
11705
    int64_t
11706
    @endcode
11707
11708
    #### Default behavior
11709
11710
    - The restrictions about leading zeros is not enforced in C++. Instead,
11711
      leading zeros in integer literals lead to an interpretation as octal
11712
      number. Internally, the value will be stored as decimal number. For
11713
      instance, the C++ integer literal `010` will be serialized to `8`.
11714
      During deserialization, leading zeros yield an error.
11715
    - Not-a-number (NaN) values will be serialized to `null`.
11716
11717
    #### Limits
11718
11719
    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
11720
    > An implementation may set limits on the range and precision of numbers.
11721
11722
    When the default type is used, the maximal integer number that can be
11723
    stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
11724
    that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
11725
    that are out of range will yield over/underflow when used in a
11726
    constructor. During deserialization, too large or small integer numbers
11727
    will be automatically be stored as @ref number_unsigned_t or @ref
11728
    number_float_t.
11729
11730
    [RFC 7159](http://rfc7159.net/rfc7159) further states:
11731
    > Note that when such software is used, numbers that are integers and are
11732
    > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
11733
    > that implementations will agree exactly on their numeric values.
11734
11735
    As this range is a subrange of the exactly supported range [INT64_MIN,
11736
    INT64_MAX], this class's integer type is interoperable.
11737
11738
    #### Storage
11739
11740
    Integer number values are stored directly inside a @ref basic_json type.
11741
11742
    @sa @ref number_float_t -- type for number values (floating-point)
11743
11744
    @sa @ref number_unsigned_t -- type for number values (unsigned integer)
11745
11746
    @since version 1.0.0
11747
    */
11748
    using number_integer_t = NumberIntegerType;
11749
11750
    /*!
11751
    @brief a type for a number (unsigned)
11752
11753
    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
11754
    > The representation of numbers is similar to that used in most
11755
    > programming languages. A number is represented in base 10 using decimal
11756
    > digits. It contains an integer component that may be prefixed with an
11757
    > optional minus sign, which may be followed by a fraction part and/or an
11758
    > exponent part. Leading zeros are not allowed. (...) Numeric values that
11759
    > cannot be represented in the grammar below (such as Infinity and NaN)
11760
    > are not permitted.
11761
11762
    This description includes both integer and floating-point numbers.
11763
    However, C++ allows more precise storage if it is known whether the number
11764
    is a signed integer, an unsigned integer or a floating-point number.
11765
    Therefore, three different types, @ref number_integer_t, @ref
11766
    number_unsigned_t and @ref number_float_t are used.
11767
11768
    To store unsigned integer numbers in C++, a type is defined by the
11769
    template parameter @a NumberUnsignedType which chooses the type to use.
11770
11771
    #### Default type
11772
11773
    With the default values for @a NumberUnsignedType (`uint64_t`), the
11774
    default value for @a number_unsigned_t is:
11775
11776
    @code {.cpp}
11777
    uint64_t
11778
    @endcode
11779
11780
    #### Default behavior
11781
11782
    - The restrictions about leading zeros is not enforced in C++. Instead,
11783
      leading zeros in integer literals lead to an interpretation as octal
11784
      number. Internally, the value will be stored as decimal number. For
11785
      instance, the C++ integer literal `010` will be serialized to `8`.
11786
      During deserialization, leading zeros yield an error.
11787
    - Not-a-number (NaN) values will be serialized to `null`.
11788
11789
    #### Limits
11790
11791
    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
11792
    > An implementation may set limits on the range and precision of numbers.
11793
11794
    When the default type is used, the maximal integer number that can be
11795
    stored is `18446744073709551615` (UINT64_MAX) and the minimal integer
11796
    number that can be stored is `0`. Integer numbers that are out of range
11797
    will yield over/underflow when used in a constructor. During
11798
    deserialization, too large or small integer numbers will be automatically
11799
    be stored as @ref number_integer_t or @ref number_float_t.
11800
11801
    [RFC 7159](http://rfc7159.net/rfc7159) further states:
11802
    > Note that when such software is used, numbers that are integers and are
11803
    > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
11804
    > that implementations will agree exactly on their numeric values.
11805
11806
    As this range is a subrange (when considered in conjunction with the
11807
    number_integer_t type) of the exactly supported range [0, UINT64_MAX],
11808
    this class's integer type is interoperable.
11809
11810
    #### Storage
11811
11812
    Integer number values are stored directly inside a @ref basic_json type.
11813
11814
    @sa @ref number_float_t -- type for number values (floating-point)
11815
    @sa @ref number_integer_t -- type for number values (integer)
11816
11817
    @since version 2.0.0
11818
    */
11819
    using number_unsigned_t = NumberUnsignedType;
11820
11821
    /*!
11822
    @brief a type for a number (floating-point)
11823
11824
    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
11825
    > The representation of numbers is similar to that used in most
11826
    > programming languages. A number is represented in base 10 using decimal
11827
    > digits. It contains an integer component that may be prefixed with an
11828
    > optional minus sign, which may be followed by a fraction part and/or an
11829
    > exponent part. Leading zeros are not allowed. (...) Numeric values that
11830
    > cannot be represented in the grammar below (such as Infinity and NaN)
11831
    > are not permitted.
11832
11833
    This description includes both integer and floating-point numbers.
11834
    However, C++ allows more precise storage if it is known whether the number
11835
    is a signed integer, an unsigned integer or a floating-point number.
11836
    Therefore, three different types, @ref number_integer_t, @ref
11837
    number_unsigned_t and @ref number_float_t are used.
11838
11839
    To store floating-point numbers in C++, a type is defined by the template
11840
    parameter @a NumberFloatType which chooses the type to use.
11841
11842
    #### Default type
11843
11844
    With the default values for @a NumberFloatType (`double`), the default
11845
    value for @a number_float_t is:
11846
11847
    @code {.cpp}
11848
    double
11849
    @endcode
11850
11851
    #### Default behavior
11852
11853
    - The restrictions about leading zeros is not enforced in C++. Instead,
11854
      leading zeros in floating-point literals will be ignored. Internally,
11855
      the value will be stored as decimal number. For instance, the C++
11856
      floating-point literal `01.2` will be serialized to `1.2`. During
11857
      deserialization, leading zeros yield an error.
11858
    - Not-a-number (NaN) values will be serialized to `null`.
11859
11860
    #### Limits
11861
11862
    [RFC 7159](http://rfc7159.net/rfc7159) states:
11863
    > This specification allows implementations to set limits on the range and
11864
    > precision of numbers accepted. Since software that implements IEEE
11865
    > 754-2008 binary64 (double precision) numbers is generally available and
11866
    > widely used, good interoperability can be achieved by implementations
11867
    > that expect no more precision or range than these provide, in the sense
11868
    > that implementations will approximate JSON numbers within the expected
11869
    > precision.
11870
11871
    This implementation does exactly follow this approach, as it uses double
11872
    precision floating-point numbers. Note values smaller than
11873
    `-1.79769313486232e+308` and values greater than `1.79769313486232e+308`
11874
    will be stored as NaN internally and be serialized to `null`.
11875
11876
    #### Storage
11877
11878
    Floating-point number values are stored directly inside a @ref basic_json
11879
    type.
11880
11881
    @sa @ref number_integer_t -- type for number values (integer)
11882
11883
    @sa @ref number_unsigned_t -- type for number values (unsigned integer)
11884
11885
    @since version 1.0.0
11886
    */
11887
    using number_float_t = NumberFloatType;
11888
11889
    /// @}
11890
11891
  private:
11892
11893
    /// helper for exception-safe object creation
11894
    template<typename T, typename... Args>
11895
    static T* create(Args&& ... args)
422k
11896
    {
422k
11897
        AllocatorType<T> alloc;
422k
11898
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
422k
11899
422k
11900
        auto deleter = [&](T * object)
0
11901
        {
0
11902
            AllocatorTraits::deallocate(alloc, object, 1);
0
11903
        };
_ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS8_JS8_EEEPT_DpOT0_ENKUlPS8_E_clESC_
0
11901
        {
0
11902
            AllocatorTraits::deallocate(alloc, object, 1);
0
11903
        };
_ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS2_ISA_SaISA_EEJEEEPT_DpOT0_ENKUlPSD_E_clESE_
0
11901
        {
0
11902
            AllocatorTraits::deallocate(alloc, object, 1);
0
11903
        };
_ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS8_JRA1_KcEEEPT_DpOT0_ENKUlPS8_E_clESF_
0
11901
        {
0
11902
            AllocatorTraits::deallocate(alloc, object, 1);
0
11903
        };
_ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS1_IS8_SA_St4lessIvESaISt4pairIKS8_SA_EEEJRKSI_EEEPT_DpOT0_ENKUlPSI_E_clESL_
0
11901
        {
0
11902
            AllocatorTraits::deallocate(alloc, object, 1);
0
11903
        };
_ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS2_ISA_SaISA_EEJRKSD_EEEPT_DpOT0_ENKUlPSD_E_clESG_
0
11901
        {
0
11902
            AllocatorTraits::deallocate(alloc, object, 1);
0
11903
        };
_ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS8_JRKS8_EEEPT_DpOT0_ENKUlPS8_E_clESE_
0
11901
        {
0
11902
            AllocatorTraits::deallocate(alloc, object, 1);
0
11903
        };
_ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS8_JRA474_KcEEEPT_DpOT0_ENKUlPS8_E_clESF_
0
11901
        {
0
11902
            AllocatorTraits::deallocate(alloc, object, 1);
0
11903
        };
_ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS8_JRA6_KcEEEPT_DpOT0_ENKUlPS8_E_clESF_
0
11901
        {
0
11902
            AllocatorTraits::deallocate(alloc, object, 1);
0
11903
        };
_ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS1_IS8_SA_St4lessIvESaISt4pairIKS8_SA_EEEJEEEPT_DpOT0_ENKUlPSI_E_clESJ_
0
11901
        {
0
11902
            AllocatorTraits::deallocate(alloc, object, 1);
0
11903
        };
_ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS8_JRKPKcEEEPT_DpOT0_ENKUlPS8_E_clESG_
0
11901
        {
0
11902
            AllocatorTraits::deallocate(alloc, object, 1);
0
11903
        };
422k
11904
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
422k
11905
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
422k
11906
        assert(object != nullptr);
422k
11907
        return object.release();
422k
11908
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS1_IS8_SA_St4lessIvESaISt4pairIKS8_SA_EEEJEEEPT_DpOT0_
141k
11896
    {
141k
11897
        AllocatorType<T> alloc;
141k
11898
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
141k
11899
141k
11900
        auto deleter = [&](T * object)
141k
11901
        {
141k
11902
            AllocatorTraits::deallocate(alloc, object, 1);
141k
11903
        };
141k
11904
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
141k
11905
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
141k
11906
        assert(object != nullptr);
141k
11907
        return object.release();
141k
11908
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS8_JRA6_KcEEEPT_DpOT0_
4
11896
    {
4
11897
        AllocatorType<T> alloc;
4
11898
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
4
11899
4
11900
        auto deleter = [&](T * object)
4
11901
        {
4
11902
            AllocatorTraits::deallocate(alloc, object, 1);
4
11903
        };
4
11904
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
4
11905
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
4
11906
        assert(object != nullptr);
4
11907
        return object.release();
4
11908
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS8_JRKPKcEEEPT_DpOT0_
40
11896
    {
40
11897
        AllocatorType<T> alloc;
40
11898
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
40
11899
40
11900
        auto deleter = [&](T * object)
40
11901
        {
40
11902
            AllocatorTraits::deallocate(alloc, object, 1);
40
11903
        };
40
11904
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
40
11905
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
40
11906
        assert(object != nullptr);
40
11907
        return object.release();
40
11908
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS8_JS8_EEEPT_DpOT0_
1.47k
11896
    {
1.47k
11897
        AllocatorType<T> alloc;
1.47k
11898
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
1.47k
11899
1.47k
11900
        auto deleter = [&](T * object)
1.47k
11901
        {
1.47k
11902
            AllocatorTraits::deallocate(alloc, object, 1);
1.47k
11903
        };
1.47k
11904
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
1.47k
11905
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
1.47k
11906
        assert(object != nullptr);
1.47k
11907
        return object.release();
1.47k
11908
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS8_JRA474_KcEEEPT_DpOT0_
548
11896
    {
548
11897
        AllocatorType<T> alloc;
548
11898
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
548
11899
548
11900
        auto deleter = [&](T * object)
548
11901
        {
548
11902
            AllocatorTraits::deallocate(alloc, object, 1);
548
11903
        };
548
11904
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
548
11905
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
548
11906
        assert(object != nullptr);
548
11907
        return object.release();
548
11908
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS1_IS8_SA_St4lessIvESaISt4pairIKS8_SA_EEEJRKSI_EEEPT_DpOT0_
18.8k
11896
    {
18.8k
11897
        AllocatorType<T> alloc;
18.8k
11898
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
18.8k
11899
18.8k
11900
        auto deleter = [&](T * object)
18.8k
11901
        {
18.8k
11902
            AllocatorTraits::deallocate(alloc, object, 1);
18.8k
11903
        };
18.8k
11904
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
18.8k
11905
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
18.8k
11906
        assert(object != nullptr);
18.8k
11907
        return object.release();
18.8k
11908
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS2_ISA_SaISA_EEJRKSD_EEEPT_DpOT0_
96
11896
    {
96
11897
        AllocatorType<T> alloc;
96
11898
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
96
11899
96
11900
        auto deleter = [&](T * object)
96
11901
        {
96
11902
            AllocatorTraits::deallocate(alloc, object, 1);
96
11903
        };
96
11904
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
96
11905
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
96
11906
        assert(object != nullptr);
96
11907
        return object.release();
96
11908
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS8_JRKS8_EEEPT_DpOT0_
258k
11896
    {
258k
11897
        AllocatorType<T> alloc;
258k
11898
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
258k
11899
258k
11900
        auto deleter = [&](T * object)
258k
11901
        {
258k
11902
            AllocatorTraits::deallocate(alloc, object, 1);
258k
11903
        };
258k
11904
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
258k
11905
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
258k
11906
        assert(object != nullptr);
258k
11907
        return object.release();
258k
11908
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS2_ISA_SaISA_EEJEEEPT_DpOT0_
1.66k
11896
    {
1.66k
11897
        AllocatorType<T> alloc;
1.66k
11898
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
1.66k
11899
1.66k
11900
        auto deleter = [&](T * object)
1.66k
11901
        {
1.66k
11902
            AllocatorTraits::deallocate(alloc, object, 1);
1.66k
11903
        };
1.66k
11904
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
1.66k
11905
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
1.66k
11906
        assert(object != nullptr);
1.66k
11907
        return object.release();
1.66k
11908
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE6createIS8_JRA1_KcEEEPT_DpOT0_
0
11896
    {
0
11897
        AllocatorType<T> alloc;
0
11898
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
0
11899
0
11900
        auto deleter = [&](T * object)
0
11901
        {
0
11902
            AllocatorTraits::deallocate(alloc, object, 1);
0
11903
        };
0
11904
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
0
11905
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
0
11906
        assert(object != nullptr);
0
11907
        return object.release();
0
11908
    }
11909
11910
    ////////////////////////
11911
    // JSON value storage //
11912
    ////////////////////////
11913
11914
    /*!
11915
    @brief a JSON value
11916
11917
    The actual storage for a JSON value of the @ref basic_json class. This
11918
    union combines the different storage types for the JSON value types
11919
    defined in @ref value_t.
11920
11921
    JSON type | value_t type    | used type
11922
    --------- | --------------- | ------------------------
11923
    object    | object          | pointer to @ref object_t
11924
    array     | array           | pointer to @ref array_t
11925
    string    | string          | pointer to @ref string_t
11926
    boolean   | boolean         | @ref boolean_t
11927
    number    | number_integer  | @ref number_integer_t
11928
    number    | number_unsigned | @ref number_unsigned_t
11929
    number    | number_float    | @ref number_float_t
11930
    null      | null            | *no value is stored*
11931
11932
    @note Variable-length types (objects, arrays, and strings) are stored as
11933
    pointers. The size of the union should not exceed 64 bits if the default
11934
    value types are used.
11935
11936
    @since version 1.0.0
11937
    */
11938
    union json_value
11939
    {
11940
        /// object (stored with pointer to save storage)
11941
        object_t* object;
11942
        /// array (stored with pointer to save storage)
11943
        array_t* array;
11944
        /// string (stored with pointer to save storage)
11945
        string_t* string;
11946
        /// boolean
11947
        boolean_t boolean;
11948
        /// number (integer)
11949
        number_integer_t number_integer;
11950
        /// number (unsigned integer)
11951
        number_unsigned_t number_unsigned;
11952
        /// number (floating-point)
11953
        number_float_t number_float;
11954
11955
        /// default constructor (for null values)
11956
        json_value() = default;
11957
        /// constructor for booleans
1.71k
11958
        json_value(boolean_t v) noexcept : boolean(v) {}
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE10json_valueC2Eb
1.71k
11958
        json_value(boolean_t v) noexcept : boolean(v) {}
_ZN8nlohmann10basic_json10json_valueC2ET2_
0
11958
        json_value(boolean_t v) noexcept : boolean(v) {}
11959
        /// constructor for numbers (integer)
27.0k
11960
        json_value(number_integer_t v) noexcept : number_integer(v) {}
_ZN8nlohmann10basic_json10json_valueC2ET3_
0
11960
        json_value(number_integer_t v) noexcept : number_integer(v) {}
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE10json_valueC2Ex
27.0k
11960
        json_value(number_integer_t v) noexcept : number_integer(v) {}
11961
        /// constructor for numbers (unsigned)
227k
11962
        json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
_ZN8nlohmann10basic_json10json_valueC2ET4_
0
11962
        json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE10json_valueC2Ey
227k
11962
        json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
11963
        /// constructor for numbers (floating-point)
168k
11964
        json_value(number_float_t v) noexcept : number_float(v) {}
_ZN8nlohmann10basic_json10json_valueC2ET5_
0
11964
        json_value(number_float_t v) noexcept : number_float(v) {}
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE10json_valueC2Ed
168k
11964
        json_value(number_float_t v) noexcept : number_float(v) {}
11965
        /// constructor for empty values of a given type
11966
        json_value(value_t t)
836k
11967
        {
836k
11968
            switch (t)
836k
11969
            {
141k
11970
                case value_t::object:
141k
11971
                {
141k
11972
                    object = create<object_t>();
141k
11973
                    break;
141k
11974
                }
141k
11975
1.66k
11976
                case value_t::array:
1.66k
11977
                {
1.66k
11978
                    array = create<array_t>();
1.66k
11979
                    break;
141k
11980
                }
141k
11981
0
11982
                case value_t::string:
0
11983
                {
0
11984
                    string = create<string_t>("");
0
11985
                    break;
141k
11986
                }
141k
11987
0
11988
                case value_t::boolean:
0
11989
                {
0
11990
                    boolean = boolean_t(false);
0
11991
                    break;
141k
11992
                }
141k
11993
0
11994
                case value_t::number_integer:
0
11995
                {
0
11996
                    number_integer = number_integer_t(0);
0
11997
                    break;
141k
11998
                }
141k
11999
0
12000
                case value_t::number_unsigned:
0
12001
                {
0
12002
                    number_unsigned = number_unsigned_t(0);
0
12003
                    break;
141k
12004
                }
141k
12005
0
12006
                case value_t::number_float:
0
12007
                {
0
12008
                    number_float = number_float_t(0.0);
0
12009
                    break;
141k
12010
                }
141k
12011
693k
12012
                case value_t::null:
693k
12013
                {
693k
12014
                    object = nullptr;  // silence warning, see #821
693k
12015
                    break;
141k
12016
                }
141k
12017
0
12018
                default:
0
12019
                {
0
12020
                    object = nullptr;  // silence warning, see #821
0
12021
                    if (JSON_UNLIKELY(t == value_t::null))
0
12022
                    {
0
12023
                        JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.2.0")); // LCOV_EXCL_LINE
0
12024
                    }
0
12025
                    break;
0
12026
                }
836k
12027
            }
836k
12028
        }
_ZN8nlohmann10basic_json10json_valueC2ENS_6detail7value_tE
0
11967
        {
0
11968
            switch (t)
0
11969
            {
0
11970
                case value_t::object:
0
11971
                {
0
11972
                    object = create<object_t>();
0
11973
                    break;
0
11974
                }
0
11975
0
11976
                case value_t::array:
0
11977
                {
0
11978
                    array = create<array_t>();
0
11979
                    break;
0
11980
                }
0
11981
0
11982
                case value_t::string:
0
11983
                {
0
11984
                    string = create<string_t>("");
0
11985
                    break;
0
11986
                }
0
11987
0
11988
                case value_t::boolean:
0
11989
                {
0
11990
                    boolean = boolean_t(false);
0
11991
                    break;
0
11992
                }
0
11993
0
11994
                case value_t::number_integer:
0
11995
                {
0
11996
                    number_integer = number_integer_t(0);
0
11997
                    break;
0
11998
                }
0
11999
0
12000
                case value_t::number_unsigned:
0
12001
                {
0
12002
                    number_unsigned = number_unsigned_t(0);
0
12003
                    break;
0
12004
                }
0
12005
0
12006
                case value_t::number_float:
0
12007
                {
0
12008
                    number_float = number_float_t(0.0);
0
12009
                    break;
0
12010
                }
0
12011
0
12012
                case value_t::null:
0
12013
                {
0
12014
                    object = nullptr;  // silence warning, see #821
0
12015
                    break;
0
12016
                }
0
12017
0
12018
                default:
0
12019
                {
0
12020
                    object = nullptr;  // silence warning, see #821
0
12021
                    if (JSON_UNLIKELY(t == value_t::null))
0
12022
                    {
0
12023
                        JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.2.0")); // LCOV_EXCL_LINE
0
12024
                    }
0
12025
                    break;
0
12026
                }
0
12027
            }
0
12028
        }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE10json_valueC2ENS_6detail7value_tE
836k
11967
        {
836k
11968
            switch (t)
836k
11969
            {
141k
11970
                case value_t::object:
141k
11971
                {
141k
11972
                    object = create<object_t>();
141k
11973
                    break;
141k
11974
                }
141k
11975
1.66k
11976
                case value_t::array:
1.66k
11977
                {
1.66k
11978
                    array = create<array_t>();
1.66k
11979
                    break;
141k
11980
                }
141k
11981
0
11982
                case value_t::string:
0
11983
                {
0
11984
                    string = create<string_t>("");
0
11985
                    break;
141k
11986
                }
141k
11987
0
11988
                case value_t::boolean:
0
11989
                {
0
11990
                    boolean = boolean_t(false);
0
11991
                    break;
141k
11992
                }
141k
11993
0
11994
                case value_t::number_integer:
0
11995
                {
0
11996
                    number_integer = number_integer_t(0);
0
11997
                    break;
141k
11998
                }
141k
11999
0
12000
                case value_t::number_unsigned:
0
12001
                {
0
12002
                    number_unsigned = number_unsigned_t(0);
0
12003
                    break;
141k
12004
                }
141k
12005
0
12006
                case value_t::number_float:
0
12007
                {
0
12008
                    number_float = number_float_t(0.0);
0
12009
                    break;
141k
12010
                }
141k
12011
693k
12012
                case value_t::null:
693k
12013
                {
693k
12014
                    object = nullptr;  // silence warning, see #821
693k
12015
                    break;
141k
12016
                }
141k
12017
0
12018
                default:
0
12019
                {
0
12020
                    object = nullptr;  // silence warning, see #821
0
12021
                    if (JSON_UNLIKELY(t == value_t::null))
0
12022
                    {
0
12023
                        JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.2.0")); // LCOV_EXCL_LINE
0
12024
                    }
0
12025
                    break;
0
12026
                }
836k
12027
            }
836k
12028
        }
12029
12030
        /// constructor for strings
12031
        json_value(const string_t& value)
258k
12032
        {
258k
12033
            string = create<string_t>(value);
258k
12034
        }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE10json_valueC2ERKS8_
258k
12032
        {
258k
12033
            string = create<string_t>(value);
258k
12034
        }
_ZN8nlohmann10basic_json10json_valueC2ERKT1_
0
12032
        {
0
12033
            string = create<string_t>(value);
0
12034
        }
12035
12036
        /// constructor for rvalue strings
12037
        json_value(string_t&& value)
1.47k
12038
        {
1.47k
12039
            string = create<string_t>(std::move(value));
1.47k
12040
        }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE10json_valueC2EOS8_
1.47k
12038
        {
1.47k
12039
            string = create<string_t>(std::move(value));
1.47k
12040
        }
_ZN8nlohmann10basic_json10json_valueC2EOT1_
0
12038
        {
0
12039
            string = create<string_t>(std::move(value));
0
12040
        }
12041
12042
        /// constructor for objects
12043
        json_value(const object_t& value)
18.8k
12044
        {
18.8k
12045
            object = create<object_t>(value);
18.8k
12046
        }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE10json_valueC2ERKS1_IS8_SA_St4lessIvESaISt4pairIKS8_SA_EEE
18.8k
12044
        {
18.8k
12045
            object = create<object_t>(value);
18.8k
12046
        }
_ZN8nlohmann10basic_json10json_valueC2ERKT_IT1_NS_10basic_jsonIS2_T0_S3_T2_T3_T4_T5_T6_T7_EEJSt4lessIvESA_ISt4pairIKS3_SD_EEEE
0
12044
        {
0
12045
            object = create<object_t>(value);
0
12046
        }
12047
12048
        /// constructor for rvalue objects
12049
        json_value(object_t&& value)
0
12050
        {
0
12051
            object = create<object_t>(std::move(value));
0
12052
        }
12053
12054
        /// constructor for arrays
12055
        json_value(const array_t& value)
96
12056
        {
96
12057
            array = create<array_t>(value);
96
12058
        }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE10json_valueC2ERKS2_ISA_SaISA_EE
96
12056
        {
96
12057
            array = create<array_t>(value);
96
12058
        }
_ZN8nlohmann10basic_json10json_valueC2ERKT0_INS_10basic_jsonIT_S2_T1_T2_T3_T4_T5_T6_T7_EEJSA_ISD_EEE
0
12056
        {
0
12057
            array = create<array_t>(value);
0
12058
        }
12059
12060
        /// constructor for rvalue arrays
12061
        json_value(array_t&& value)
0
12062
        {
0
12063
            array = create<array_t>(std::move(value));
0
12064
        }
12065
12066
        void destroy(value_t t) noexcept
1.57M
12067
        {
1.57M
12068
            switch (t)
1.57M
12069
            {
160k
12070
                case value_t::object:
160k
12071
                {
160k
12072
                    AllocatorType<object_t> alloc;
160k
12073
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
160k
12074
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
160k
12075
                    break;
160k
12076
                }
160k
12077
1.75k
12078
                case value_t::array:
1.75k
12079
                {
1.75k
12080
                    AllocatorType<array_t> alloc;
1.75k
12081
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
1.75k
12082
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
1.75k
12083
                    break;
160k
12084
                }
160k
12085
260k
12086
                case value_t::string:
260k
12087
                {
260k
12088
                    AllocatorType<string_t> alloc;
260k
12089
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
260k
12090
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
260k
12091
                    break;
160k
12092
                }
160k
12093
1.15M
12094
                default:
1.15M
12095
                {
1.15M
12096
                    break;
160k
12097
                }
1.57M
12098
            }
1.57M
12099
        }
_ZN8nlohmann10basic_json10json_value7destroyENS_6detail7value_tE
0
12067
        {
0
12068
            switch (t)
0
12069
            {
0
12070
                case value_t::object:
0
12071
                {
0
12072
                    AllocatorType<object_t> alloc;
0
12073
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
0
12074
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
0
12075
                    break;
0
12076
                }
0
12077
0
12078
                case value_t::array:
0
12079
                {
0
12080
                    AllocatorType<array_t> alloc;
0
12081
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
0
12082
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
0
12083
                    break;
0
12084
                }
0
12085
0
12086
                case value_t::string:
0
12087
                {
0
12088
                    AllocatorType<string_t> alloc;
0
12089
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
0
12090
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
0
12091
                    break;
0
12092
                }
0
12093
0
12094
                default:
0
12095
                {
0
12096
                    break;
0
12097
                }
0
12098
            }
0
12099
        }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE10json_value7destroyENS_6detail7value_tE
1.57M
12067
        {
1.57M
12068
            switch (t)
1.57M
12069
            {
160k
12070
                case value_t::object:
160k
12071
                {
160k
12072
                    AllocatorType<object_t> alloc;
160k
12073
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
160k
12074
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
160k
12075
                    break;
160k
12076
                }
160k
12077
1.75k
12078
                case value_t::array:
1.75k
12079
                {
1.75k
12080
                    AllocatorType<array_t> alloc;
1.75k
12081
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
1.75k
12082
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
1.75k
12083
                    break;
160k
12084
                }
160k
12085
260k
12086
                case value_t::string:
260k
12087
                {
260k
12088
                    AllocatorType<string_t> alloc;
260k
12089
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
260k
12090
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
260k
12091
                    break;
160k
12092
                }
160k
12093
1.15M
12094
                default:
1.15M
12095
                {
1.15M
12096
                    break;
160k
12097
                }
1.57M
12098
            }
1.57M
12099
        }
12100
    };
12101
12102
    /*!
12103
    @brief checks the class invariants
12104
12105
    This function asserts the class invariants. It needs to be called at the
12106
    end of every constructor to make sure that created objects respect the
12107
    invariant. Furthermore, it has to be called each time the type of a JSON
12108
    value is changed, because the invariant expresses a relationship between
12109
    @a m_type and @a m_value.
12110
    */
12111
    void assert_invariant() const noexcept
5.96M
12112
    {
5.96M
12113
        assert(m_type != value_t::object or m_value.object != nullptr);
5.96M
12114
        assert(m_type != value_t::array or m_value.array != nullptr);
5.96M
12115
        assert(m_type != value_t::string or m_value.string != nullptr);
5.96M
12116
    }
12117
12118
  public:
12119
    //////////////////////////
12120
    // JSON parser callback //
12121
    //////////////////////////
12122
12123
    /*!
12124
    @brief parser event types
12125
12126
    The parser callback distinguishes the following events:
12127
    - `object_start`: the parser read `{` and started to process a JSON object
12128
    - `key`: the parser read a key of a value in an object
12129
    - `object_end`: the parser read `}` and finished processing a JSON object
12130
    - `array_start`: the parser read `[` and started to process a JSON array
12131
    - `array_end`: the parser read `]` and finished processing a JSON array
12132
    - `value`: the parser finished reading a JSON value
12133
12134
    @image html callback_events.png "Example when certain parse events are triggered"
12135
12136
    @sa @ref parser_callback_t for more information and examples
12137
    */
12138
    using parse_event_t = typename parser::parse_event_t;
12139
12140
    /*!
12141
    @brief per-element parser callback type
12142
12143
    With a parser callback function, the result of parsing a JSON text can be
12144
    influenced. When passed to @ref parse, it is called on certain events
12145
    (passed as @ref parse_event_t via parameter @a event) with a set recursion
12146
    depth @a depth and context JSON value @a parsed. The return value of the
12147
    callback function is a boolean indicating whether the element that emitted
12148
    the callback shall be kept or not.
12149
12150
    We distinguish six scenarios (determined by the event type) in which the
12151
    callback function can be called. The following table describes the values
12152
    of the parameters @a depth, @a event, and @a parsed.
12153
12154
    parameter @a event | description | parameter @a depth | parameter @a parsed
12155
    ------------------ | ----------- | ------------------ | -------------------
12156
    parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
12157
    parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
12158
    parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
12159
    parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
12160
    parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
12161
    parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
12162
12163
    @image html callback_events.png "Example when certain parse events are triggered"
12164
12165
    Discarding a value (i.e., returning `false`) has different effects
12166
    depending on the context in which function was called:
12167
12168
    - Discarded values in structured types are skipped. That is, the parser
12169
      will behave as if the discarded value was never read.
12170
    - In case a value outside a structured type is skipped, it is replaced
12171
      with `null`. This case happens if the top-level element is skipped.
12172
12173
    @param[in] depth  the depth of the recursion during parsing
12174
12175
    @param[in] event  an event of type parse_event_t indicating the context in
12176
    the callback function has been called
12177
12178
    @param[in,out] parsed  the current intermediate parse result; note that
12179
    writing to this value has no effect for parse_event_t::key events
12180
12181
    @return Whether the JSON value which called the function during parsing
12182
    should be kept (`true`) or not (`false`). In the latter case, it is either
12183
    skipped completely or replaced by an empty discarded object.
12184
12185
    @sa @ref parse for examples
12186
12187
    @since version 1.0.0
12188
    */
12189
    using parser_callback_t = typename parser::parser_callback_t;
12190
12191
    //////////////////
12192
    // constructors //
12193
    //////////////////
12194
12195
    /// @name constructors and destructors
12196
    /// Constructors of class @ref basic_json, copy/move constructor, copy
12197
    /// assignment, static functions creating objects, and the destructor.
12198
    /// @{
12199
12200
    /*!
12201
    @brief create an empty value with a given type
12202
12203
    Create an empty JSON value with a given type. The value will be default
12204
    initialized with an empty value which depends on the type:
12205
12206
    Value type  | initial value
12207
    ----------- | -------------
12208
    null        | `null`
12209
    boolean     | `false`
12210
    string      | `""`
12211
    number      | `0`
12212
    object      | `{}`
12213
    array       | `[]`
12214
12215
    @param[in] v  the type of the value to create
12216
12217
    @complexity Constant.
12218
12219
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12220
    changes to any JSON value.
12221
12222
    @liveexample{The following code shows the constructor for different @ref
12223
    value_t values,basic_json__value_t}
12224
12225
    @sa @ref clear() -- restores the postcondition of this constructor
12226
12227
    @since version 1.0.0
12228
    */
12229
    basic_json(const value_t v)
12230
        : m_type(v), m_value(v)
835k
12231
    {
835k
12232
        assert_invariant();
835k
12233
    }
12234
12235
    /*!
12236
    @brief create a null object
12237
12238
    Create a `null` JSON value. It either takes a null pointer as parameter
12239
    (explicitly creating `null`) or no parameter (implicitly creating `null`).
12240
    The passed null pointer itself is not read -- it is only used to choose
12241
    the right constructor.
12242
12243
    @complexity Constant.
12244
12245
    @exceptionsafety No-throw guarantee: this constructor never throws
12246
    exceptions.
12247
12248
    @liveexample{The following code shows the constructor with and without a
12249
    null pointer parameter.,basic_json__nullptr_t}
12250
12251
    @since version 1.0.0
12252
    */
12253
    basic_json(std::nullptr_t = nullptr) noexcept
12254
        : basic_json(value_t::null)
693k
12255
    {
693k
12256
        assert_invariant();
693k
12257
    }
12258
12259
    /*!
12260
    @brief create a JSON value
12261
12262
    This is a "catch all" constructor for all compatible JSON types; that is,
12263
    types for which a `to_json()` method exists. The constructor forwards the
12264
    parameter @a val to that method (to `json_serializer<U>::to_json` method
12265
    with `U = uncvref_t<CompatibleType>`, to be exact).
12266
12267
    Template type @a CompatibleType includes, but is not limited to, the
12268
    following types:
12269
    - **arrays**: @ref array_t and all kinds of compatible containers such as
12270
      `std::vector`, `std::deque`, `std::list`, `std::forward_list`,
12271
      `std::array`, `std::valarray`, `std::set`, `std::unordered_set`,
12272
      `std::multiset`, and `std::unordered_multiset` with a `value_type` from
12273
      which a @ref basic_json value can be constructed.
12274
    - **objects**: @ref object_t and all kinds of compatible associative
12275
      containers such as `std::map`, `std::unordered_map`, `std::multimap`,
12276
      and `std::unordered_multimap` with a `key_type` compatible to
12277
      @ref string_t and a `value_type` from which a @ref basic_json value can
12278
      be constructed.
12279
    - **strings**: @ref string_t, string literals, and all compatible string
12280
      containers can be used.
12281
    - **numbers**: @ref number_integer_t, @ref number_unsigned_t,
12282
      @ref number_float_t, and all convertible number types such as `int`,
12283
      `size_t`, `int64_t`, `float` or `double` can be used.
12284
    - **boolean**: @ref boolean_t / `bool` can be used.
12285
12286
    See the examples below.
12287
12288
    @tparam CompatibleType a type such that:
12289
    - @a CompatibleType is not derived from `std::istream`,
12290
    - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move
12291
         constructors),
12292
    - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments)
12293
    - @a CompatibleType is not a @ref basic_json nested type (e.g.,
12294
         @ref json_pointer, @ref iterator, etc ...)
12295
    - @ref @ref json_serializer<U> has a
12296
         `to_json(basic_json_t&, CompatibleType&&)` method
12297
12298
    @tparam U = `uncvref_t<CompatibleType>`
12299
12300
    @param[in] val the value to be forwarded to the respective constructor
12301
12302
    @complexity Usually linear in the size of the passed @a val, also
12303
                depending on the implementation of the called `to_json()`
12304
                method.
12305
12306
    @exceptionsafety Depends on the called constructor. For types directly
12307
    supported by the library (i.e., all types for which no `to_json()` function
12308
    was provided), strong guarantee holds: if an exception is thrown, there are
12309
    no changes to any JSON value.
12310
12311
    @liveexample{The following code shows the constructor with several
12312
    compatible types.,basic_json__CompatibleType}
12313
12314
    @since version 2.1.0
12315
    */
12316
    template <typename CompatibleType,
12317
              typename U = detail::uncvref_t<CompatibleType>,
12318
              detail::enable_if_t<
12319
                  not detail::is_basic_json<U>::value and detail::is_compatible_type<basic_json_t, U>::value, int> = 0>
12320
    basic_json(CompatibleType && val) noexcept(noexcept(
12321
                JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
12322
                                           std::forward<CompatibleType>(val))))
573k
12323
    {
573k
12324
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
573k
12325
        assert_invariant();
573k
12326
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEC2IddLi0EEEOT_
4
12323
    {
4
12324
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
4
12325
        assert_invariant();
4
12326
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEC2IKS8_S8_Li0EEEOT_
164
12323
    {
164
12324
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
164
12325
        assert_invariant();
164
12326
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEC2IRjjLi0EEEOT_
492
12323
    {
492
12324
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
492
12325
        assert_invariant();
492
12326
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEC2IRKPKcSD_Li0EEEOT_
40
12323
    {
40
12324
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
40
12325
        assert_invariant();
40
12326
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEC2IbbLi0EEEOT_
4
12323
    {
4
12324
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
4
12325
        assert_invariant();
4
12326
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEC2IS8_S8_Li0EEEOT_
1.47k
12323
    {
1.47k
12324
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
1.47k
12325
        assert_invariant();
1.47k
12326
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEC2IRA6_KcA6_cLi0EEEOT_
4
12323
    {
4
12324
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
4
12325
        assert_invariant();
4
12326
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEC2IiiLi0EEEOT_
4
12323
    {
4
12324
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
4
12325
        assert_invariant();
4
12326
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEC2IRS8_S8_Li0EEEOT_
172k
12323
    {
172k
12324
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
172k
12325
        assert_invariant();
172k
12326
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEC2IRddLi0EEEOT_
158k
12323
    {
158k
12324
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
158k
12325
        assert_invariant();
158k
12326
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEC2IRbbLi0EEEOT_
1.66k
12323
    {
1.66k
12324
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
1.66k
12325
        assert_invariant();
1.66k
12326
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEC2IRxxLi0EEEOT_
25.3k
12323
    {
25.3k
12324
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
25.3k
12325
        assert_invariant();
25.3k
12326
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEC2IRyyLi0EEEOT_
212k
12323
    {
212k
12324
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
212k
12325
        assert_invariant();
212k
12326
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEEC2IRA474_KcA474_cLi0EEEOT_
548
12323
    {
548
12324
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
548
12325
        assert_invariant();
548
12326
    }
12327
12328
    /*!
12329
    @brief create a JSON value from an existing one
12330
12331
    This is a constructor for existing @ref basic_json types.
12332
    It does not hijack copy/move constructors, since the parameter has different
12333
    template arguments than the current ones.
12334
12335
    The constructor tries to convert the internal @ref m_value of the parameter.
12336
12337
    @tparam BasicJsonType a type such that:
12338
    - @a BasicJsonType is a @ref basic_json type.
12339
    - @a BasicJsonType has different template arguments than @ref basic_json_t.
12340
12341
    @param[in] val the @ref basic_json value to be converted.
12342
12343
    @complexity Usually linear in the size of the passed @a val, also
12344
                depending on the implementation of the called `to_json()`
12345
                method.
12346
12347
    @exceptionsafety Depends on the called constructor. For types directly
12348
    supported by the library (i.e., all types for which no `to_json()` function
12349
    was provided), strong guarantee holds: if an exception is thrown, there are
12350
    no changes to any JSON value.
12351
12352
    @since version 3.2.0
12353
    */
12354
    template <typename BasicJsonType,
12355
              detail::enable_if_t<
12356
                  detail::is_basic_json<BasicJsonType>::value and not std::is_same<basic_json, BasicJsonType>::value, int> = 0>
12357
    basic_json(const BasicJsonType& val)
12358
    {
12359
        using other_boolean_t = typename BasicJsonType::boolean_t;
12360
        using other_number_float_t = typename BasicJsonType::number_float_t;
12361
        using other_number_integer_t = typename BasicJsonType::number_integer_t;
12362
        using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12363
        using other_string_t = typename BasicJsonType::string_t;
12364
        using other_object_t = typename BasicJsonType::object_t;
12365
        using other_array_t = typename BasicJsonType::array_t;
12366
12367
        switch (val.type())
12368
        {
12369
            case value_t::boolean:
12370
                JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
12371
                break;
12372
            case value_t::number_float:
12373
                JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
12374
                break;
12375
            case value_t::number_integer:
12376
                JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
12377
                break;
12378
            case value_t::number_unsigned:
12379
                JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
12380
                break;
12381
            case value_t::string:
12382
                JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
12383
                break;
12384
            case value_t::object:
12385
                JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
12386
                break;
12387
            case value_t::array:
12388
                JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
12389
                break;
12390
            case value_t::null:
12391
                *this = nullptr;
12392
                break;
12393
            case value_t::discarded:
12394
                m_type = value_t::discarded;
12395
                break;
12396
        }
12397
        assert_invariant();
12398
    }
12399
12400
    /*!
12401
    @brief create a container (array or object) from an initializer list
12402
12403
    Creates a JSON value of type array or object from the passed initializer
12404
    list @a init. In case @a type_deduction is `true` (default), the type of
12405
    the JSON value to be created is deducted from the initializer list @a init
12406
    according to the following rules:
12407
12408
    1. If the list is empty, an empty JSON object value `{}` is created.
12409
    2. If the list consists of pairs whose first element is a string, a JSON
12410
       object value is created where the first elements of the pairs are
12411
       treated as keys and the second elements are as values.
12412
    3. In all other cases, an array is created.
12413
12414
    The rules aim to create the best fit between a C++ initializer list and
12415
    JSON values. The rationale is as follows:
12416
12417
    1. The empty initializer list is written as `{}` which is exactly an empty
12418
       JSON object.
12419
    2. C++ has no way of describing mapped types other than to list a list of
12420
       pairs. As JSON requires that keys must be of type string, rule 2 is the
12421
       weakest constraint one can pose on initializer lists to interpret them
12422
       as an object.
12423
    3. In all other cases, the initializer list could not be interpreted as
12424
       JSON object type, so interpreting it as JSON array type is safe.
12425
12426
    With the rules described above, the following JSON values cannot be
12427
    expressed by an initializer list:
12428
12429
    - the empty array (`[]`): use @ref array(initializer_list_t)
12430
      with an empty initializer list in this case
12431
    - arrays whose elements satisfy rule 2: use @ref
12432
      array(initializer_list_t) with the same initializer list
12433
      in this case
12434
12435
    @note When used without parentheses around an empty initializer list, @ref
12436
    basic_json() is called instead of this function, yielding the JSON null
12437
    value.
12438
12439
    @param[in] init  initializer list with JSON values
12440
12441
    @param[in] type_deduction internal parameter; when set to `true`, the type
12442
    of the JSON value is deducted from the initializer list @a init; when set
12443
    to `false`, the type provided via @a manual_type is forced. This mode is
12444
    used by the functions @ref array(initializer_list_t) and
12445
    @ref object(initializer_list_t).
12446
12447
    @param[in] manual_type internal parameter; when @a type_deduction is set
12448
    to `false`, the created JSON value will use the provided type (only @ref
12449
    value_t::array and @ref value_t::object are valid); when @a type_deduction
12450
    is set to `true`, this parameter has no effect
12451
12452
    @throw type_error.301 if @a type_deduction is `false`, @a manual_type is
12453
    `value_t::object`, but @a init contains an element which is not a pair
12454
    whose first element is a string. In this case, the constructor could not
12455
    create an object. If @a type_deduction would have be `true`, an array
12456
    would have been created. See @ref object(initializer_list_t)
12457
    for an example.
12458
12459
    @complexity Linear in the size of the initializer list @a init.
12460
12461
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12462
    changes to any JSON value.
12463
12464
    @liveexample{The example below shows how JSON values are created from
12465
    initializer lists.,basic_json__list_init_t}
12466
12467
    @sa @ref array(initializer_list_t) -- create a JSON array
12468
    value from an initializer list
12469
    @sa @ref object(initializer_list_t) -- create a JSON object
12470
    value from an initializer list
12471
12472
    @since version 1.0.0
12473
    */
12474
    basic_json(initializer_list_t init,
12475
               bool type_deduction = true,
12476
               value_t manual_type = value_t::array)
12477
    {
12478
        // check if each element is an array with two elements whose first
12479
        // element is a string
12480
        bool is_an_object = std::all_of(init.begin(), init.end(),
12481
                                        [](const detail::json_ref<basic_json>& element_ref)
12482
        {
12483
            return (element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string());
12484
        });
12485
12486
        // adjust type if type deduction is not wanted
12487
        if (not type_deduction)
12488
        {
12489
            // if array is wanted, do not create an object though possible
12490
            if (manual_type == value_t::array)
12491
            {
12492
                is_an_object = false;
12493
            }
12494
12495
            // if object is wanted but impossible, throw an exception
12496
            if (JSON_UNLIKELY(manual_type == value_t::object and not is_an_object))
12497
            {
12498
                JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
12499
            }
12500
        }
12501
12502
        if (is_an_object)
12503
        {
12504
            // the initializer list is a list of pairs -> create object
12505
            m_type = value_t::object;
12506
            m_value = value_t::object;
12507
12508
            std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
12509
            {
12510
                auto element = element_ref.moved_or_copied();
12511
                m_value.object->emplace(
12512
                    std::move(*((*element.m_value.array)[0].m_value.string)),
12513
                    std::move((*element.m_value.array)[1]));
12514
            });
12515
        }
12516
        else
12517
        {
12518
            // the initializer list describes an array -> create array
12519
            m_type = value_t::array;
12520
            m_value.array = create<array_t>(init.begin(), init.end());
12521
        }
12522
12523
        assert_invariant();
12524
    }
12525
12526
    /*!
12527
    @brief explicitly create an array from an initializer list
12528
12529
    Creates a JSON array value from a given initializer list. That is, given a
12530
    list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the
12531
    initializer list is empty, the empty array `[]` is created.
12532
12533
    @note This function is only needed to express two edge cases that cannot
12534
    be realized with the initializer list constructor (@ref
12535
    basic_json(initializer_list_t, bool, value_t)). These cases
12536
    are:
12537
    1. creating an array whose elements are all pairs whose first element is a
12538
    string -- in this case, the initializer list constructor would create an
12539
    object, taking the first elements as keys
12540
    2. creating an empty array -- passing the empty initializer list to the
12541
    initializer list constructor yields an empty object
12542
12543
    @param[in] init  initializer list with JSON values to create an array from
12544
    (optional)
12545
12546
    @return JSON array value
12547
12548
    @complexity Linear in the size of @a init.
12549
12550
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12551
    changes to any JSON value.
12552
12553
    @liveexample{The following code shows an example for the `array`
12554
    function.,array}
12555
12556
    @sa @ref basic_json(initializer_list_t, bool, value_t) --
12557
    create a JSON value from an initializer list
12558
    @sa @ref object(initializer_list_t) -- create a JSON object
12559
    value from an initializer list
12560
12561
    @since version 1.0.0
12562
    */
12563
    static basic_json array(initializer_list_t init = {})
12564
    {
12565
        return basic_json(init, false, value_t::array);
12566
    }
12567
12568
    /*!
12569
    @brief explicitly create an object from an initializer list
12570
12571
    Creates a JSON object value from a given initializer list. The initializer
12572
    lists elements must be pairs, and their first elements must be strings. If
12573
    the initializer list is empty, the empty object `{}` is created.
12574
12575
    @note This function is only added for symmetry reasons. In contrast to the
12576
    related function @ref array(initializer_list_t), there are
12577
    no cases which can only be expressed by this function. That is, any
12578
    initializer list @a init can also be passed to the initializer list
12579
    constructor @ref basic_json(initializer_list_t, bool, value_t).
12580
12581
    @param[in] init  initializer list to create an object from (optional)
12582
12583
    @return JSON object value
12584
12585
    @throw type_error.301 if @a init is not a list of pairs whose first
12586
    elements are strings. In this case, no object can be created. When such a
12587
    value is passed to @ref basic_json(initializer_list_t, bool, value_t),
12588
    an array would have been created from the passed initializer list @a init.
12589
    See example below.
12590
12591
    @complexity Linear in the size of @a init.
12592
12593
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12594
    changes to any JSON value.
12595
12596
    @liveexample{The following code shows an example for the `object`
12597
    function.,object}
12598
12599
    @sa @ref basic_json(initializer_list_t, bool, value_t) --
12600
    create a JSON value from an initializer list
12601
    @sa @ref array(initializer_list_t) -- create a JSON array
12602
    value from an initializer list
12603
12604
    @since version 1.0.0
12605
    */
12606
    static basic_json object(initializer_list_t init = {})
12607
    {
12608
        return basic_json(init, false, value_t::object);
12609
    }
12610
12611
    /*!
12612
    @brief construct an array with count copies of given value
12613
12614
    Constructs a JSON array value by creating @a cnt copies of a passed value.
12615
    In case @a cnt is `0`, an empty array is created.
12616
12617
    @param[in] cnt  the number of JSON copies of @a val to create
12618
    @param[in] val  the JSON value to copy
12619
12620
    @post `std::distance(begin(),end()) == cnt` holds.
12621
12622
    @complexity Linear in @a cnt.
12623
12624
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12625
    changes to any JSON value.
12626
12627
    @liveexample{The following code shows examples for the @ref
12628
    basic_json(size_type\, const basic_json&)
12629
    constructor.,basic_json__size_type_basic_json}
12630
12631
    @since version 1.0.0
12632
    */
12633
    basic_json(size_type cnt, const basic_json& val)
12634
        : m_type(value_t::array)
12635
    {
12636
        m_value.array = create<array_t>(cnt, val);
12637
        assert_invariant();
12638
    }
12639
12640
    /*!
12641
    @brief construct a JSON container given an iterator range
12642
12643
    Constructs the JSON value with the contents of the range `[first, last)`.
12644
    The semantics depends on the different types a JSON value can have:
12645
    - In case of a null type, invalid_iterator.206 is thrown.
12646
    - In case of other primitive types (number, boolean, or string), @a first
12647
      must be `begin()` and @a last must be `end()`. In this case, the value is
12648
      copied. Otherwise, invalid_iterator.204 is thrown.
12649
    - In case of structured types (array, object), the constructor behaves as
12650
      similar versions for `std::vector` or `std::map`; that is, a JSON array
12651
      or object is constructed from the values in the range.
12652
12653
    @tparam InputIT an input iterator type (@ref iterator or @ref
12654
    const_iterator)
12655
12656
    @param[in] first begin of the range to copy from (included)
12657
    @param[in] last end of the range to copy from (excluded)
12658
12659
    @pre Iterators @a first and @a last must be initialized. **This
12660
         precondition is enforced with an assertion (see warning).** If
12661
         assertions are switched off, a violation of this precondition yields
12662
         undefined behavior.
12663
12664
    @pre Range `[first, last)` is valid. Usually, this precondition cannot be
12665
         checked efficiently. Only certain edge cases are detected; see the
12666
         description of the exceptions below. A violation of this precondition
12667
         yields undefined behavior.
12668
12669
    @warning A precondition is enforced with a runtime assertion that will
12670
             result in calling `std::abort` if this precondition is not met.
12671
             Assertions can be disabled by defining `NDEBUG` at compile time.
12672
             See https://en.cppreference.com/w/cpp/error/assert for more
12673
             information.
12674
12675
    @throw invalid_iterator.201 if iterators @a first and @a last are not
12676
    compatible (i.e., do not belong to the same JSON value). In this case,
12677
    the range `[first, last)` is undefined.
12678
    @throw invalid_iterator.204 if iterators @a first and @a last belong to a
12679
    primitive type (number, boolean, or string), but @a first does not point
12680
    to the first element any more. In this case, the range `[first, last)` is
12681
    undefined. See example code below.
12682
    @throw invalid_iterator.206 if iterators @a first and @a last belong to a
12683
    null value. In this case, the range `[first, last)` is undefined.
12684
12685
    @complexity Linear in distance between @a first and @a last.
12686
12687
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12688
    changes to any JSON value.
12689
12690
    @liveexample{The example below shows several ways to create JSON values by
12691
    specifying a subrange with iterators.,basic_json__InputIt_InputIt}
12692
12693
    @since version 1.0.0
12694
    */
12695
    template<class InputIT, typename std::enable_if<
12696
                 std::is_same<InputIT, typename basic_json_t::iterator>::value or
12697
                 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
12698
    basic_json(InputIT first, InputIT last)
12699
    {
12700
        assert(first.m_object != nullptr);
12701
        assert(last.m_object != nullptr);
12702
12703
        // make sure iterator fits the current value
12704
        if (JSON_UNLIKELY(first.m_object != last.m_object))
12705
        {
12706
            JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
12707
        }
12708
12709
        // copy type from first iterator
12710
        m_type = first.m_object->m_type;
12711
12712
        // check if iterator range is complete for primitive values
12713
        switch (m_type)
12714
        {
12715
            case value_t::boolean:
12716
            case value_t::number_float:
12717
            case value_t::number_integer:
12718
            case value_t::number_unsigned:
12719
            case value_t::string:
12720
            {
12721
                if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin()
12722
                                  or not last.m_it.primitive_iterator.is_end()))
12723
                {
12724
                    JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
12725
                }
12726
                break;
12727
            }
12728
12729
            default:
12730
                break;
12731
        }
12732
12733
        switch (m_type)
12734
        {
12735
            case value_t::number_integer:
12736
            {
12737
                m_value.number_integer = first.m_object->m_value.number_integer;
12738
                break;
12739
            }
12740
12741
            case value_t::number_unsigned:
12742
            {
12743
                m_value.number_unsigned = first.m_object->m_value.number_unsigned;
12744
                break;
12745
            }
12746
12747
            case value_t::number_float:
12748
            {
12749
                m_value.number_float = first.m_object->m_value.number_float;
12750
                break;
12751
            }
12752
12753
            case value_t::boolean:
12754
            {
12755
                m_value.boolean = first.m_object->m_value.boolean;
12756
                break;
12757
            }
12758
12759
            case value_t::string:
12760
            {
12761
                m_value = *first.m_object->m_value.string;
12762
                break;
12763
            }
12764
12765
            case value_t::object:
12766
            {
12767
                m_value.object = create<object_t>(first.m_it.object_iterator,
12768
                                                  last.m_it.object_iterator);
12769
                break;
12770
            }
12771
12772
            case value_t::array:
12773
            {
12774
                m_value.array = create<array_t>(first.m_it.array_iterator,
12775
                                                last.m_it.array_iterator);
12776
                break;
12777
            }
12778
12779
            default:
12780
                JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
12781
                                                    std::string(first.m_object->type_name())));
12782
        }
12783
12784
        assert_invariant();
12785
    }
12786
12787
12788
    ///////////////////////////////////////
12789
    // other constructors and destructor //
12790
    ///////////////////////////////////////
12791
12792
    /// @private
12793
    basic_json(const detail::json_ref<basic_json>& ref)
12794
        : basic_json(ref.moved_or_copied())
12795
    {}
12796
12797
    /*!
12798
    @brief copy constructor
12799
12800
    Creates a copy of a given JSON value.
12801
12802
    @param[in] other  the JSON value to copy
12803
12804
    @post `*this == other`
12805
12806
    @complexity Linear in the size of @a other.
12807
12808
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12809
    changes to any JSON value.
12810
12811
    @requirement This function helps `basic_json` satisfying the
12812
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
12813
    requirements:
12814
    - The complexity is linear.
12815
    - As postcondition, it holds: `other == basic_json(other)`.
12816
12817
    @liveexample{The following code shows an example for the copy
12818
    constructor.,basic_json__basic_json}
12819
12820
    @since version 1.0.0
12821
    */
12822
    basic_json(const basic_json& other)
12823
        : m_type(other.m_type)
131k
12824
    {
131k
12825
        // check of passed value is valid
131k
12826
        other.assert_invariant();
131k
12827
131k
12828
        switch (m_type)
131k
12829
        {
18.8k
12830
            case value_t::object:
18.8k
12831
            {
18.8k
12832
                m_value = *other.m_value.object;
18.8k
12833
                break;
18.8k
12834
            }
18.8k
12835
96
12836
            case value_t::array:
96
12837
            {
96
12838
                m_value = *other.m_value.array;
96
12839
                break;
18.8k
12840
            }
18.8k
12841
86.0k
12842
            case value_t::string:
86.0k
12843
            {
86.0k
12844
                m_value = *other.m_value.string;
86.0k
12845
                break;
18.8k
12846
            }
18.8k
12847
48
12848
            case value_t::boolean:
48
12849
            {
48
12850
                m_value = other.m_value.boolean;
48
12851
                break;
18.8k
12852
            }
18.8k
12853
1.68k
12854
            case value_t::number_integer:
1.68k
12855
            {
1.68k
12856
                m_value = other.m_value.number_integer;
1.68k
12857
                break;
18.8k
12858
            }
18.8k
12859
14.5k
12860
            case value_t::number_unsigned:
14.5k
12861
            {
14.5k
12862
                m_value = other.m_value.number_unsigned;
14.5k
12863
                break;
18.8k
12864
            }
18.8k
12865
10.5k
12866
            case value_t::number_float:
10.5k
12867
            {
10.5k
12868
                m_value = other.m_value.number_float;
10.5k
12869
                break;
18.8k
12870
            }
18.8k
12871
32
12872
            default:
32
12873
                break;
131k
12874
        }
131k
12875
131k
12876
        assert_invariant();
131k
12877
    }
12878
12879
    /*!
12880
    @brief move constructor
12881
12882
    Move constructor. Constructs a JSON value with the contents of the given
12883
    value @a other using move semantics. It "steals" the resources from @a
12884
    other and leaves it as JSON null value.
12885
12886
    @param[in,out] other  value to move to this object
12887
12888
    @post `*this` has the same value as @a other before the call.
12889
    @post @a other is a JSON null value.
12890
12891
    @complexity Constant.
12892
12893
    @exceptionsafety No-throw guarantee: this constructor never throws
12894
    exceptions.
12895
12896
    @requirement This function helps `basic_json` satisfying the
12897
    [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible)
12898
    requirements.
12899
12900
    @liveexample{The code below shows the move constructor explicitly called
12901
    via std::move.,basic_json__moveconstructor}
12902
12903
    @since version 1.0.0
12904
    */
12905
    basic_json(basic_json&& other) noexcept
12906
        : m_type(std::move(other.m_type)),
12907
          m_value(std::move(other.m_value))
34.1k
12908
    {
34.1k
12909
        // check that passed value is valid
34.1k
12910
        other.assert_invariant();
34.1k
12911
34.1k
12912
        // invalidate payload
34.1k
12913
        other.m_type = value_t::null;
34.1k
12914
        other.m_value = {};
34.1k
12915
34.1k
12916
        assert_invariant();
34.1k
12917
    }
12918
12919
    /*!
12920
    @brief copy assignment
12921
12922
    Copy assignment operator. Copies a JSON value via the "copy and swap"
12923
    strategy: It is expressed in terms of the copy constructor, destructor,
12924
    and the `swap()` member function.
12925
12926
    @param[in] other  value to copy from
12927
12928
    @complexity Linear.
12929
12930
    @requirement This function helps `basic_json` satisfying the
12931
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
12932
    requirements:
12933
    - The complexity is linear.
12934
12935
    @liveexample{The code below shows and example for the copy assignment. It
12936
    creates a copy of value `a` which is then swapped with `b`. Finally\, the
12937
    copy of `a` (which is the null value after the swap) is
12938
    destroyed.,basic_json__copyassignment}
12939
12940
    @since version 1.0.0
12941
    */
12942
    reference& operator=(basic_json other) noexcept (
12943
        std::is_nothrow_move_constructible<value_t>::value and
12944
        std::is_nothrow_move_assignable<value_t>::value and
12945
        std::is_nothrow_move_constructible<json_value>::value and
12946
        std::is_nothrow_move_assignable<json_value>::value
12947
    )
690k
12948
    {
690k
12949
        // check that passed value is valid
690k
12950
        other.assert_invariant();
690k
12951
690k
12952
        using std::swap;
690k
12953
        swap(m_type, other.m_type);
690k
12954
        swap(m_value, other.m_value);
690k
12955
690k
12956
        assert_invariant();
690k
12957
        return *this;
690k
12958
    }
12959
12960
    /*!
12961
    @brief destructor
12962
12963
    Destroys the JSON value and frees all allocated memory.
12964
12965
    @complexity Linear.
12966
12967
    @requirement This function helps `basic_json` satisfying the
12968
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
12969
    requirements:
12970
    - The complexity is linear.
12971
    - All stored elements are destroyed and all memory is freed.
12972
12973
    @since version 1.0.0
12974
    */
12975
    ~basic_json() noexcept
1.57M
12976
    {
1.57M
12977
        assert_invariant();
1.57M
12978
        m_value.destroy(m_type);
1.57M
12979
    }
12980
12981
    /// @}
12982
12983
  public:
12984
    ///////////////////////
12985
    // object inspection //
12986
    ///////////////////////
12987
12988
    /// @name object inspection
12989
    /// Functions to inspect the type of a JSON value.
12990
    /// @{
12991
12992
    /*!
12993
    @brief serialization
12994
12995
    Serialization function for JSON values. The function tries to mimic
12996
    Python's `json.dumps()` function, and currently supports its @a indent
12997
    and @a ensure_ascii parameters.
12998
12999
    @param[in] indent If indent is nonnegative, then array elements and object
13000
    members will be pretty-printed with that indent level. An indent level of
13001
    `0` will only insert newlines. `-1` (the default) selects the most compact
13002
    representation.
13003
    @param[in] indent_char The character to use for indentation if @a indent is
13004
    greater than `0`. The default is ` ` (space).
13005
    @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
13006
    in the output are escaped with `\uXXXX` sequences, and the result consists
13007
    of ASCII characters only.
13008
13009
    @return string containing the serialization of the JSON value
13010
13011
    @throw type_error.316 if a string stored inside the JSON value is not
13012
                          UTF-8 encoded
13013
13014
    @complexity Linear.
13015
13016
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13017
    changes in the JSON value.
13018
13019
    @liveexample{The following example shows the effect of different @a indent\,
13020
    @a indent_char\, and @a ensure_ascii parameters to the result of the
13021
    serialization.,dump}
13022
13023
    @see https://docs.python.org/2/library/json.html#json.dump
13024
13025
    @since version 1.0.0; indentation character @a indent_char, option
13026
           @a ensure_ascii and exceptions added in version 3.0.0
13027
    */
13028
    string_t dump(const int indent = -1, const char indent_char = ' ',
13029
                  const bool ensure_ascii = false) const
68
13030
    {
68
13031
        string_t result;
68
13032
        serializer s(detail::output_adapter<char, string_t>(result), indent_char);
68
13033
68
13034
        if (indent >= 0)
60
13035
        {
60
13036
            s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
60
13037
        }
68
13038
        else
8
13039
        {
8
13040
            s.dump(*this, false, ensure_ascii, 0);
8
13041
        }
68
13042
68
13043
        return result;
68
13044
    }
13045
13046
    /*!
13047
    @brief return the type of the JSON value (explicit)
13048
13049
    Return the type of the JSON value as a value from the @ref value_t
13050
    enumeration.
13051
13052
    @return the type of the JSON value
13053
            Value type                | return value
13054
            ------------------------- | -------------------------
13055
            null                      | value_t::null
13056
            boolean                   | value_t::boolean
13057
            string                    | value_t::string
13058
            number (integer)          | value_t::number_integer
13059
            number (unsigned integer) | value_t::number_unsigned
13060
            number (floating-point)   | value_t::number_float
13061
            object                    | value_t::object
13062
            array                     | value_t::array
13063
            discarded                 | value_t::discarded
13064
13065
    @complexity Constant.
13066
13067
    @exceptionsafety No-throw guarantee: this member function never throws
13068
    exceptions.
13069
13070
    @liveexample{The following code exemplifies `type()` for all JSON
13071
    types.,type}
13072
13073
    @sa @ref operator value_t() -- return the type of the JSON value (implicit)
13074
    @sa @ref type_name() -- return the type as string
13075
13076
    @since version 1.0.0
13077
    */
13078
    constexpr value_t type() const noexcept
80
13079
    {
80
13080
        return m_type;
80
13081
    }
13082
13083
    /*!
13084
    @brief return whether type is primitive
13085
13086
    This function returns true if and only if the JSON type is primitive
13087
    (string, number, boolean, or null).
13088
13089
    @return `true` if type is primitive (string, number, boolean, or null),
13090
    `false` otherwise.
13091
13092
    @complexity Constant.
13093
13094
    @exceptionsafety No-throw guarantee: this member function never throws
13095
    exceptions.
13096
13097
    @liveexample{The following code exemplifies `is_primitive()` for all JSON
13098
    types.,is_primitive}
13099
13100
    @sa @ref is_structured() -- returns whether JSON value is structured
13101
    @sa @ref is_null() -- returns whether JSON value is `null`
13102
    @sa @ref is_string() -- returns whether JSON value is a string
13103
    @sa @ref is_boolean() -- returns whether JSON value is a boolean
13104
    @sa @ref is_number() -- returns whether JSON value is a number
13105
13106
    @since version 1.0.0
13107
    */
13108
    constexpr bool is_primitive() const noexcept
13109
    {
13110
        return is_null() or is_string() or is_boolean() or is_number();
13111
    }
13112
13113
    /*!
13114
    @brief return whether type is structured
13115
13116
    This function returns true if and only if the JSON type is structured
13117
    (array or object).
13118
13119
    @return `true` if type is structured (array or object), `false` otherwise.
13120
13121
    @complexity Constant.
13122
13123
    @exceptionsafety No-throw guarantee: this member function never throws
13124
    exceptions.
13125
13126
    @liveexample{The following code exemplifies `is_structured()` for all JSON
13127
    types.,is_structured}
13128
13129
    @sa @ref is_primitive() -- returns whether value is primitive
13130
    @sa @ref is_array() -- returns whether value is an array
13131
    @sa @ref is_object() -- returns whether value is an object
13132
13133
    @since version 1.0.0
13134
    */
13135
    constexpr bool is_structured() const noexcept
13136
    {
13137
        return is_array() or is_object();
13138
    }
13139
13140
    /*!
13141
    @brief return whether value is null
13142
13143
    This function returns true if and only if the JSON value is null.
13144
13145
    @return `true` if type is null, `false` otherwise.
13146
13147
    @complexity Constant.
13148
13149
    @exceptionsafety No-throw guarantee: this member function never throws
13150
    exceptions.
13151
13152
    @liveexample{The following code exemplifies `is_null()` for all JSON
13153
    types.,is_null}
13154
13155
    @since version 1.0.0
13156
    */
13157
    constexpr bool is_null() const noexcept
6.10k
13158
    {
6.10k
13159
        return (m_type == value_t::null);
6.10k
13160
    }
13161
13162
    /*!
13163
    @brief return whether value is a boolean
13164
13165
    This function returns true if and only if the JSON value is a boolean.
13166
13167
    @return `true` if type is boolean, `false` otherwise.
13168
13169
    @complexity Constant.
13170
13171
    @exceptionsafety No-throw guarantee: this member function never throws
13172
    exceptions.
13173
13174
    @liveexample{The following code exemplifies `is_boolean()` for all JSON
13175
    types.,is_boolean}
13176
13177
    @since version 1.0.0
13178
    */
13179
    constexpr bool is_boolean() const noexcept
16
13180
    {
16
13181
        return (m_type == value_t::boolean);
16
13182
    }
13183
13184
    /*!
13185
    @brief return whether value is a number
13186
13187
    This function returns true if and only if the JSON value is a number. This
13188
    includes both integer (signed and unsigned) and floating-point values.
13189
13190
    @return `true` if type is number (regardless whether integer, unsigned
13191
    integer or floating-type), `false` otherwise.
13192
13193
    @complexity Constant.
13194
13195
    @exceptionsafety No-throw guarantee: this member function never throws
13196
    exceptions.
13197
13198
    @liveexample{The following code exemplifies `is_number()` for all JSON
13199
    types.,is_number}
13200
13201
    @sa @ref is_number_integer() -- check if value is an integer or unsigned
13202
    integer number
13203
    @sa @ref is_number_unsigned() -- check if value is an unsigned integer
13204
    number
13205
    @sa @ref is_number_float() -- check if value is a floating-point number
13206
13207
    @since version 1.0.0
13208
    */
13209
    constexpr bool is_number() const noexcept
13210
    {
13211
        return is_number_integer() or is_number_float();
13212
    }
13213
13214
    /*!
13215
    @brief return whether value is an integer number
13216
13217
    This function returns true if and only if the JSON value is a signed or
13218
    unsigned integer number. This excludes floating-point values.
13219
13220
    @return `true` if type is an integer or unsigned integer number, `false`
13221
    otherwise.
13222
13223
    @complexity Constant.
13224
13225
    @exceptionsafety No-throw guarantee: this member function never throws
13226
    exceptions.
13227
13228
    @liveexample{The following code exemplifies `is_number_integer()` for all
13229
    JSON types.,is_number_integer}
13230
13231
    @sa @ref is_number() -- check if value is a number
13232
    @sa @ref is_number_unsigned() -- check if value is an unsigned integer
13233
    number
13234
    @sa @ref is_number_float() -- check if value is a floating-point number
13235
13236
    @since version 1.0.0
13237
    */
13238
    constexpr bool is_number_integer() const noexcept
0
13239
    {
0
13240
        return (m_type == value_t::number_integer or m_type == value_t::number_unsigned);
0
13241
    }
13242
13243
    /*!
13244
    @brief return whether value is an unsigned integer number
13245
13246
    This function returns true if and only if the JSON value is an unsigned
13247
    integer number. This excludes floating-point and signed integer values.
13248
13249
    @return `true` if type is an unsigned integer number, `false` otherwise.
13250
13251
    @complexity Constant.
13252
13253
    @exceptionsafety No-throw guarantee: this member function never throws
13254
    exceptions.
13255
13256
    @liveexample{The following code exemplifies `is_number_unsigned()` for all
13257
    JSON types.,is_number_unsigned}
13258
13259
    @sa @ref is_number() -- check if value is a number
13260
    @sa @ref is_number_integer() -- check if value is an integer or unsigned
13261
    integer number
13262
    @sa @ref is_number_float() -- check if value is a floating-point number
13263
13264
    @since version 2.0.0
13265
    */
13266
    constexpr bool is_number_unsigned() const noexcept
608
13267
    {
608
13268
        return (m_type == value_t::number_unsigned);
608
13269
    }
13270
13271
    /*!
13272
    @brief return whether value is a floating-point number
13273
13274
    This function returns true if and only if the JSON value is a
13275
    floating-point number. This excludes signed and unsigned integer values.
13276
13277
    @return `true` if type is a floating-point number, `false` otherwise.
13278
13279
    @complexity Constant.
13280
13281
    @exceptionsafety No-throw guarantee: this member function never throws
13282
    exceptions.
13283
13284
    @liveexample{The following code exemplifies `is_number_float()` for all
13285
    JSON types.,is_number_float}
13286
13287
    @sa @ref is_number() -- check if value is number
13288
    @sa @ref is_number_integer() -- check if value is an integer number
13289
    @sa @ref is_number_unsigned() -- check if value is an unsigned integer
13290
    number
13291
13292
    @since version 1.0.0
13293
    */
13294
    constexpr bool is_number_float() const noexcept
592
13295
    {
592
13296
        return (m_type == value_t::number_float);
592
13297
    }
13298
13299
    /*!
13300
    @brief return whether value is an object
13301
13302
    This function returns true if and only if the JSON value is an object.
13303
13304
    @return `true` if type is object, `false` otherwise.
13305
13306
    @complexity Constant.
13307
13308
    @exceptionsafety No-throw guarantee: this member function never throws
13309
    exceptions.
13310
13311
    @liveexample{The following code exemplifies `is_object()` for all JSON
13312
    types.,is_object}
13313
13314
    @since version 1.0.0
13315
    */
13316
    constexpr bool is_object() const noexcept
723k
13317
    {
723k
13318
        return (m_type == value_t::object);
723k
13319
    }
13320
13321
    /*!
13322
    @brief return whether value is an array
13323
13324
    This function returns true if and only if the JSON value is an array.
13325
13326
    @return `true` if type is array, `false` otherwise.
13327
13328
    @complexity Constant.
13329
13330
    @exceptionsafety No-throw guarantee: this member function never throws
13331
    exceptions.
13332
13333
    @liveexample{The following code exemplifies `is_array()` for all JSON
13334
    types.,is_array}
13335
13336
    @since version 1.0.0
13337
    */
13338
    constexpr bool is_array() const noexcept
1.41M
13339
    {
1.41M
13340
        return (m_type == value_t::array);
1.41M
13341
    }
13342
13343
    /*!
13344
    @brief return whether value is a string
13345
13346
    This function returns true if and only if the JSON value is a string.
13347
13348
    @return `true` if type is string, `false` otherwise.
13349
13350
    @complexity Constant.
13351
13352
    @exceptionsafety No-throw guarantee: this member function never throws
13353
    exceptions.
13354
13355
    @liveexample{The following code exemplifies `is_string()` for all JSON
13356
    types.,is_string}
13357
13358
    @since version 1.0.0
13359
    */
13360
    constexpr bool is_string() const noexcept
62.4k
13361
    {
62.4k
13362
        return (m_type == value_t::string);
62.4k
13363
    }
13364
13365
    /*!
13366
    @brief return whether value is discarded
13367
13368
    This function returns true if and only if the JSON value was discarded
13369
    during parsing with a callback function (see @ref parser_callback_t).
13370
13371
    @note This function will always be `false` for JSON values after parsing.
13372
    That is, discarded values can only occur during parsing, but will be
13373
    removed when inside a structured value or replaced by null in other cases.
13374
13375
    @return `true` if type is discarded, `false` otherwise.
13376
13377
    @complexity Constant.
13378
13379
    @exceptionsafety No-throw guarantee: this member function never throws
13380
    exceptions.
13381
13382
    @liveexample{The following code exemplifies `is_discarded()` for all JSON
13383
    types.,is_discarded}
13384
13385
    @since version 1.0.0
13386
    */
13387
    constexpr bool is_discarded() const noexcept
0
13388
    {
0
13389
        return (m_type == value_t::discarded);
0
13390
    }
13391
13392
    /*!
13393
    @brief return the type of the JSON value (implicit)
13394
13395
    Implicitly return the type of the JSON value as a value from the @ref
13396
    value_t enumeration.
13397
13398
    @return the type of the JSON value
13399
13400
    @complexity Constant.
13401
13402
    @exceptionsafety No-throw guarantee: this member function never throws
13403
    exceptions.
13404
13405
    @liveexample{The following code exemplifies the @ref value_t operator for
13406
    all JSON types.,operator__value_t}
13407
13408
    @sa @ref type() -- return the type of the JSON value (explicit)
13409
    @sa @ref type_name() -- return the type as string
13410
13411
    @since version 1.0.0
13412
    */
13413
    constexpr operator value_t() const noexcept
1.20k
13414
    {
1.20k
13415
        return m_type;
1.20k
13416
    }
13417
13418
    /// @}
13419
13420
  private:
13421
    //////////////////
13422
    // value access //
13423
    //////////////////
13424
13425
    /// get a boolean (explicit)
13426
    boolean_t get_impl(boolean_t* /*unused*/) const
13427
    {
13428
        if (JSON_LIKELY(is_boolean()))
13429
        {
13430
            return m_value.boolean;
13431
        }
13432
13433
        JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
13434
    }
13435
13436
    /// get a pointer to the value (object)
13437
    object_t* get_impl_ptr(object_t* /*unused*/) noexcept
13438
    {
13439
        return is_object() ? m_value.object : nullptr;
13440
    }
13441
13442
    /// get a pointer to the value (object)
13443
    constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
13444
    {
13445
        return is_object() ? m_value.object : nullptr;
13446
    }
13447
13448
    /// get a pointer to the value (array)
13449
    array_t* get_impl_ptr(array_t* /*unused*/) noexcept
13450
    {
13451
        return is_array() ? m_value.array : nullptr;
13452
    }
13453
13454
    /// get a pointer to the value (array)
13455
    constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
13456
    {
13457
        return is_array() ? m_value.array : nullptr;
13458
    }
13459
13460
    /// get a pointer to the value (string)
13461
    string_t* get_impl_ptr(string_t* /*unused*/) noexcept
13462
    {
13463
        return is_string() ? m_value.string : nullptr;
13464
    }
13465
13466
    /// get a pointer to the value (string)
13467
    constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
31.2k
13468
    {
31.2k
13469
        return is_string() ? m_value.string : nullptr;
31.2k
13470
    }
13471
13472
    /// get a pointer to the value (boolean)
13473
    boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
13474
    {
13475
        return is_boolean() ? &m_value.boolean : nullptr;
13476
    }
13477
13478
    /// get a pointer to the value (boolean)
13479
    constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
8
13480
    {
8
13481
        return is_boolean() ? &m_value.boolean : nullptr;
8
13482
    }
13483
13484
    /// get a pointer to the value (integer number)
13485
    number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
13486
    {
13487
        return is_number_integer() ? &m_value.number_integer : nullptr;
13488
    }
13489
13490
    /// get a pointer to the value (integer number)
13491
    constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
0
13492
    {
0
13493
        return is_number_integer() ? &m_value.number_integer : nullptr;
0
13494
    }
13495
13496
    /// get a pointer to the value (unsigned number)
13497
    number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
13498
    {
13499
        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
13500
    }
13501
13502
    /// get a pointer to the value (unsigned number)
13503
    constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
608
13504
    {
608
13505
        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
608
13506
    }
13507
13508
    /// get a pointer to the value (floating-point number)
13509
    number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
13510
    {
13511
        return is_number_float() ? &m_value.number_float : nullptr;
13512
    }
13513
13514
    /// get a pointer to the value (floating-point number)
13515
    constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
592
13516
    {
592
13517
        return is_number_float() ? &m_value.number_float : nullptr;
592
13518
    }
13519
13520
    /*!
13521
    @brief helper function to implement get_ref()
13522
13523
    This function helps to implement get_ref() without code duplication for
13524
    const and non-const overloads
13525
13526
    @tparam ThisType will be deduced as `basic_json` or `const basic_json`
13527
13528
    @throw type_error.303 if ReferenceType does not match underlying value
13529
    type of the current JSON
13530
    */
13531
    template<typename ReferenceType, typename ThisType>
13532
    static ReferenceType get_ref_impl(ThisType& obj)
13533
    {
13534
        // delegate the call to get_ptr<>()
13535
        auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
13536
13537
        if (JSON_LIKELY(ptr != nullptr))
13538
        {
13539
            return *ptr;
13540
        }
13541
13542
        JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
13543
    }
13544
13545
  public:
13546
    /// @name value access
13547
    /// Direct access to the stored value of a JSON value.
13548
    /// @{
13549
13550
    /*!
13551
    @brief get special-case overload
13552
13553
    This overloads avoids a lot of template boilerplate, it can be seen as the
13554
    identity method
13555
13556
    @tparam BasicJsonType == @ref basic_json
13557
13558
    @return a copy of *this
13559
13560
    @complexity Constant.
13561
13562
    @since version 2.1.0
13563
    */
13564
    template<typename BasicJsonType, detail::enable_if_t<
13565
                 std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
13566
                 int> = 0>
13567
    basic_json get() const
48
13568
    {
48
13569
        return *this;
48
13570
    }
13571
13572
    /*!
13573
    @brief get special-case overload
13574
13575
    This overloads converts the current @ref basic_json in a different
13576
    @ref basic_json type
13577
13578
    @tparam BasicJsonType == @ref basic_json
13579
13580
    @return a copy of *this, converted into @tparam BasicJsonType
13581
13582
    @complexity Depending on the implementation of the called `from_json()`
13583
                method.
13584
13585
    @since version 3.2.0
13586
    */
13587
    template<typename BasicJsonType, detail::enable_if_t<
13588
                 not std::is_same<BasicJsonType, basic_json>::value and
13589
                 detail::is_basic_json<BasicJsonType>::value, int> = 0>
13590
    BasicJsonType get() const
13591
    {
13592
        return *this;
13593
    }
13594
13595
    /*!
13596
    @brief get a value (explicit)
13597
13598
    Explicit type conversion between the JSON value and a compatible value
13599
    which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
13600
    and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
13601
    The value is converted by calling the @ref json_serializer<ValueType>
13602
    `from_json()` method.
13603
13604
    The function is equivalent to executing
13605
    @code {.cpp}
13606
    ValueType ret;
13607
    JSONSerializer<ValueType>::from_json(*this, ret);
13608
    return ret;
13609
    @endcode
13610
13611
    This overloads is chosen if:
13612
    - @a ValueType is not @ref basic_json,
13613
    - @ref json_serializer<ValueType> has a `from_json()` method of the form
13614
      `void from_json(const basic_json&, ValueType&)`, and
13615
    - @ref json_serializer<ValueType> does not have a `from_json()` method of
13616
      the form `ValueType from_json(const basic_json&)`
13617
13618
    @tparam ValueTypeCV the provided value type
13619
    @tparam ValueType the returned value type
13620
13621
    @return copy of the JSON value, converted to @a ValueType
13622
13623
    @throw what @ref json_serializer<ValueType> `from_json()` method throws
13624
13625
    @liveexample{The example below shows several conversions from JSON values
13626
    to other types. There a few things to note: (1) Floating-point numbers can
13627
    be converted to integers\, (2) A JSON array can be converted to a standard
13628
    `std::vector<short>`\, (3) A JSON object can be converted to C++
13629
    associative containers such as `std::unordered_map<std::string\,
13630
    json>`.,get__ValueType_const}
13631
13632
    @since version 2.1.0
13633
    */
13634
    template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
13635
             detail::enable_if_t <
13636
                 not detail::is_basic_json<ValueType>::value and
13637
                 detail::has_from_json<basic_json_t, ValueType>::value and
13638
                 not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
13639
                 int> = 0>
13640
    ValueType get() const noexcept(noexcept(
13641
                                       JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
32.4k
13642
    {
32.4k
13643
        // we cannot static_assert on ValueTypeCV being non-const, because
32.4k
13644
        // there is support for get<const basic_json_t>(), which is why we
32.4k
13645
        // still need the uncvref
32.4k
13646
        static_assert(not std::is_reference<ValueTypeCV>::value,
32.4k
13647
                      "get() cannot be used with reference types, you might want to use get_ref()");
32.4k
13648
        static_assert(std::is_default_constructible<ValueType>::value,
32.4k
13649
                      "types must be DefaultConstructible when used with get()");
32.4k
13650
32.4k
13651
        ValueType ret;
32.4k
13652
        JSONSerializer<ValueType>::from_json(*this, ret);
32.4k
13653
        return ret;
32.4k
13654
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE3getIddLi0EEET0_v
592
13642
    {
592
13643
        // we cannot static_assert on ValueTypeCV being non-const, because
592
13644
        // there is support for get<const basic_json_t>(), which is why we
592
13645
        // still need the uncvref
592
13646
        static_assert(not std::is_reference<ValueTypeCV>::value,
592
13647
                      "get() cannot be used with reference types, you might want to use get_ref()");
592
13648
        static_assert(std::is_default_constructible<ValueType>::value,
592
13649
                      "types must be DefaultConstructible when used with get()");
592
13650
592
13651
        ValueType ret;
592
13652
        JSONSerializer<ValueType>::from_json(*this, ret);
592
13653
        return ret;
592
13654
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE3getIiiLi0EEET0_v
608
13642
    {
608
13643
        // we cannot static_assert on ValueTypeCV being non-const, because
608
13644
        // there is support for get<const basic_json_t>(), which is why we
608
13645
        // still need the uncvref
608
13646
        static_assert(not std::is_reference<ValueTypeCV>::value,
608
13647
                      "get() cannot be used with reference types, you might want to use get_ref()");
608
13648
        static_assert(std::is_default_constructible<ValueType>::value,
608
13649
                      "types must be DefaultConstructible when used with get()");
608
13650
608
13651
        ValueType ret;
608
13652
        JSONSerializer<ValueType>::from_json(*this, ret);
608
13653
        return ret;
608
13654
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE3getIS8_S8_Li0EEET0_v
31.2k
13642
    {
31.2k
13643
        // we cannot static_assert on ValueTypeCV being non-const, because
31.2k
13644
        // there is support for get<const basic_json_t>(), which is why we
31.2k
13645
        // still need the uncvref
31.2k
13646
        static_assert(not std::is_reference<ValueTypeCV>::value,
31.2k
13647
                      "get() cannot be used with reference types, you might want to use get_ref()");
31.2k
13648
        static_assert(std::is_default_constructible<ValueType>::value,
31.2k
13649
                      "types must be DefaultConstructible when used with get()");
31.2k
13650
31.2k
13651
        ValueType ret;
31.2k
13652
        JSONSerializer<ValueType>::from_json(*this, ret);
31.2k
13653
        return ret;
31.2k
13654
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE3getIbbLi0EEET0_v
8
13642
    {
8
13643
        // we cannot static_assert on ValueTypeCV being non-const, because
8
13644
        // there is support for get<const basic_json_t>(), which is why we
8
13645
        // still need the uncvref
8
13646
        static_assert(not std::is_reference<ValueTypeCV>::value,
8
13647
                      "get() cannot be used with reference types, you might want to use get_ref()");
8
13648
        static_assert(std::is_default_constructible<ValueType>::value,
8
13649
                      "types must be DefaultConstructible when used with get()");
8
13650
8
13651
        ValueType ret;
8
13652
        JSONSerializer<ValueType>::from_json(*this, ret);
8
13653
        return ret;
8
13654
    }
13655
13656
    /*!
13657
    @brief get a value (explicit); special case
13658
13659
    Explicit type conversion between the JSON value and a compatible value
13660
    which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
13661
    and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
13662
    The value is converted by calling the @ref json_serializer<ValueType>
13663
    `from_json()` method.
13664
13665
    The function is equivalent to executing
13666
    @code {.cpp}
13667
    return JSONSerializer<ValueTypeCV>::from_json(*this);
13668
    @endcode
13669
13670
    This overloads is chosen if:
13671
    - @a ValueType is not @ref basic_json and
13672
    - @ref json_serializer<ValueType> has a `from_json()` method of the form
13673
      `ValueType from_json(const basic_json&)`
13674
13675
    @note If @ref json_serializer<ValueType> has both overloads of
13676
    `from_json()`, this one is chosen.
13677
13678
    @tparam ValueTypeCV the provided value type
13679
    @tparam ValueType the returned value type
13680
13681
    @return copy of the JSON value, converted to @a ValueType
13682
13683
    @throw what @ref json_serializer<ValueType> `from_json()` method throws
13684
13685
    @since version 2.1.0
13686
    */
13687
    template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
13688
             detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
13689
                                 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
13690
                                 int> = 0>
13691
    ValueType get() const noexcept(noexcept(
13692
                                       JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))
13693
    {
13694
        static_assert(not std::is_reference<ValueTypeCV>::value,
13695
                      "get() cannot be used with reference types, you might want to use get_ref()");
13696
        return JSONSerializer<ValueTypeCV>::from_json(*this);
13697
    }
13698
13699
    /*!
13700
    @brief get a pointer value (explicit)
13701
13702
    Explicit pointer access to the internally stored JSON value. No copies are
13703
    made.
13704
13705
    @warning The pointer becomes invalid if the underlying JSON object
13706
    changes.
13707
13708
    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
13709
    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
13710
    @ref number_unsigned_t, or @ref number_float_t.
13711
13712
    @return pointer to the internally stored JSON value if the requested
13713
    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
13714
13715
    @complexity Constant.
13716
13717
    @liveexample{The example below shows how pointers to internal values of a
13718
    JSON value can be requested. Note that no type conversions are made and a
13719
    `nullptr` is returned if the value and the requested pointer type does not
13720
    match.,get__PointerType}
13721
13722
    @sa @ref get_ptr() for explicit pointer-member access
13723
13724
    @since version 1.0.0
13725
    */
13726
    template<typename PointerType, typename std::enable_if<
13727
                 std::is_pointer<PointerType>::value, int>::type = 0>
13728
    PointerType get() noexcept
13729
    {
13730
        // delegate the call to get_ptr
13731
        return get_ptr<PointerType>();
13732
    }
13733
13734
    /*!
13735
    @brief get a pointer value (explicit)
13736
    @copydoc get()
13737
    */
13738
    template<typename PointerType, typename std::enable_if<
13739
                 std::is_pointer<PointerType>::value, int>::type = 0>
13740
    constexpr const PointerType get() const noexcept
13741
    {
13742
        // delegate the call to get_ptr
13743
        return get_ptr<PointerType>();
13744
    }
13745
13746
    /*!
13747
    @brief get a pointer value (implicit)
13748
13749
    Implicit pointer access to the internally stored JSON value. No copies are
13750
    made.
13751
13752
    @warning Writing data to the pointee of the result yields an undefined
13753
    state.
13754
13755
    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
13756
    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
13757
    @ref number_unsigned_t, or @ref number_float_t. Enforced by a static
13758
    assertion.
13759
13760
    @return pointer to the internally stored JSON value if the requested
13761
    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
13762
13763
    @complexity Constant.
13764
13765
    @liveexample{The example below shows how pointers to internal values of a
13766
    JSON value can be requested. Note that no type conversions are made and a
13767
    `nullptr` is returned if the value and the requested pointer type does not
13768
    match.,get_ptr}
13769
13770
    @since version 1.0.0
13771
    */
13772
    template<typename PointerType, typename std::enable_if<
13773
                 std::is_pointer<PointerType>::value, int>::type = 0>
13774
    PointerType get_ptr() noexcept
13775
    {
13776
        // get the type of the PointerType (remove pointer and const)
13777
        using pointee_t = typename std::remove_const<typename
13778
                          std::remove_pointer<typename
13779
                          std::remove_const<PointerType>::type>::type>::type;
13780
        // make sure the type matches the allowed types
13781
        static_assert(
13782
            std::is_same<object_t, pointee_t>::value
13783
            or std::is_same<array_t, pointee_t>::value
13784
            or std::is_same<string_t, pointee_t>::value
13785
            or std::is_same<boolean_t, pointee_t>::value
13786
            or std::is_same<number_integer_t, pointee_t>::value
13787
            or std::is_same<number_unsigned_t, pointee_t>::value
13788
            or std::is_same<number_float_t, pointee_t>::value
13789
            , "incompatible pointer type");
13790
13791
        // delegate the call to get_impl_ptr<>()
13792
        return get_impl_ptr(static_cast<PointerType>(nullptr));
13793
    }
13794
13795
    /*!
13796
    @brief get a pointer value (implicit)
13797
    @copydoc get_ptr()
13798
    */
13799
    template<typename PointerType, typename std::enable_if<
13800
                 std::is_pointer<PointerType>::value and
13801
                 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
13802
    constexpr const PointerType get_ptr() const noexcept
32.4k
13803
    {
32.4k
13804
        // get the type of the PointerType (remove pointer and const)
32.4k
13805
        using pointee_t = typename std::remove_const<typename
32.4k
13806
                          std::remove_pointer<typename
32.4k
13807
                          std::remove_const<PointerType>::type>::type>::type;
32.4k
13808
        // make sure the type matches the allowed types
32.4k
13809
        static_assert(
32.4k
13810
            std::is_same<object_t, pointee_t>::value
32.4k
13811
            or std::is_same<array_t, pointee_t>::value
32.4k
13812
            or std::is_same<string_t, pointee_t>::value
32.4k
13813
            or std::is_same<boolean_t, pointee_t>::value
32.4k
13814
            or std::is_same<number_integer_t, pointee_t>::value
32.4k
13815
            or std::is_same<number_unsigned_t, pointee_t>::value
32.4k
13816
            or std::is_same<number_float_t, pointee_t>::value
32.4k
13817
            , "incompatible pointer type");
32.4k
13818
32.4k
13819
        // delegate the call to get_impl_ptr<>() const
32.4k
13820
        return get_impl_ptr(static_cast<PointerType>(nullptr));
32.4k
13821
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE7get_ptrIPKyLi0EEEKT_v
608
13803
    {
608
13804
        // get the type of the PointerType (remove pointer and const)
608
13805
        using pointee_t = typename std::remove_const<typename
608
13806
                          std::remove_pointer<typename
608
13807
                          std::remove_const<PointerType>::type>::type>::type;
608
13808
        // make sure the type matches the allowed types
608
13809
        static_assert(
608
13810
            std::is_same<object_t, pointee_t>::value
608
13811
            or std::is_same<array_t, pointee_t>::value
608
13812
            or std::is_same<string_t, pointee_t>::value
608
13813
            or std::is_same<boolean_t, pointee_t>::value
608
13814
            or std::is_same<number_integer_t, pointee_t>::value
608
13815
            or std::is_same<number_unsigned_t, pointee_t>::value
608
13816
            or std::is_same<number_float_t, pointee_t>::value
608
13817
            , "incompatible pointer type");
608
13818
608
13819
        // delegate the call to get_impl_ptr<>() const
608
13820
        return get_impl_ptr(static_cast<PointerType>(nullptr));
608
13821
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE7get_ptrIPKbLi0EEEKT_v
8
13803
    {
8
13804
        // get the type of the PointerType (remove pointer and const)
8
13805
        using pointee_t = typename std::remove_const<typename
8
13806
                          std::remove_pointer<typename
8
13807
                          std::remove_const<PointerType>::type>::type>::type;
8
13808
        // make sure the type matches the allowed types
8
13809
        static_assert(
8
13810
            std::is_same<object_t, pointee_t>::value
8
13811
            or std::is_same<array_t, pointee_t>::value
8
13812
            or std::is_same<string_t, pointee_t>::value
8
13813
            or std::is_same<boolean_t, pointee_t>::value
8
13814
            or std::is_same<number_integer_t, pointee_t>::value
8
13815
            or std::is_same<number_unsigned_t, pointee_t>::value
8
13816
            or std::is_same<number_float_t, pointee_t>::value
8
13817
            , "incompatible pointer type");
8
13818
8
13819
        // delegate the call to get_impl_ptr<>() const
8
13820
        return get_impl_ptr(static_cast<PointerType>(nullptr));
8
13821
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE7get_ptrIPKS8_Li0EEEKT_v
31.2k
13803
    {
31.2k
13804
        // get the type of the PointerType (remove pointer and const)
31.2k
13805
        using pointee_t = typename std::remove_const<typename
31.2k
13806
                          std::remove_pointer<typename
31.2k
13807
                          std::remove_const<PointerType>::type>::type>::type;
31.2k
13808
        // make sure the type matches the allowed types
31.2k
13809
        static_assert(
31.2k
13810
            std::is_same<object_t, pointee_t>::value
31.2k
13811
            or std::is_same<array_t, pointee_t>::value
31.2k
13812
            or std::is_same<string_t, pointee_t>::value
31.2k
13813
            or std::is_same<boolean_t, pointee_t>::value
31.2k
13814
            or std::is_same<number_integer_t, pointee_t>::value
31.2k
13815
            or std::is_same<number_unsigned_t, pointee_t>::value
31.2k
13816
            or std::is_same<number_float_t, pointee_t>::value
31.2k
13817
            , "incompatible pointer type");
31.2k
13818
31.2k
13819
        // delegate the call to get_impl_ptr<>() const
31.2k
13820
        return get_impl_ptr(static_cast<PointerType>(nullptr));
31.2k
13821
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE7get_ptrIPKxLi0EEEKT_v
0
13803
    {
0
13804
        // get the type of the PointerType (remove pointer and const)
0
13805
        using pointee_t = typename std::remove_const<typename
0
13806
                          std::remove_pointer<typename
0
13807
                          std::remove_const<PointerType>::type>::type>::type;
0
13808
        // make sure the type matches the allowed types
0
13809
        static_assert(
0
13810
            std::is_same<object_t, pointee_t>::value
0
13811
            or std::is_same<array_t, pointee_t>::value
0
13812
            or std::is_same<string_t, pointee_t>::value
0
13813
            or std::is_same<boolean_t, pointee_t>::value
0
13814
            or std::is_same<number_integer_t, pointee_t>::value
0
13815
            or std::is_same<number_unsigned_t, pointee_t>::value
0
13816
            or std::is_same<number_float_t, pointee_t>::value
0
13817
            , "incompatible pointer type");
0
13818
0
13819
        // delegate the call to get_impl_ptr<>() const
0
13820
        return get_impl_ptr(static_cast<PointerType>(nullptr));
0
13821
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE7get_ptrIPKdLi0EEEKT_v
592
13803
    {
592
13804
        // get the type of the PointerType (remove pointer and const)
592
13805
        using pointee_t = typename std::remove_const<typename
592
13806
                          std::remove_pointer<typename
592
13807
                          std::remove_const<PointerType>::type>::type>::type;
592
13808
        // make sure the type matches the allowed types
592
13809
        static_assert(
592
13810
            std::is_same<object_t, pointee_t>::value
592
13811
            or std::is_same<array_t, pointee_t>::value
592
13812
            or std::is_same<string_t, pointee_t>::value
592
13813
            or std::is_same<boolean_t, pointee_t>::value
592
13814
            or std::is_same<number_integer_t, pointee_t>::value
592
13815
            or std::is_same<number_unsigned_t, pointee_t>::value
592
13816
            or std::is_same<number_float_t, pointee_t>::value
592
13817
            , "incompatible pointer type");
592
13818
592
13819
        // delegate the call to get_impl_ptr<>() const
592
13820
        return get_impl_ptr(static_cast<PointerType>(nullptr));
592
13821
    }
13822
13823
    /*!
13824
    @brief get a reference value (implicit)
13825
13826
    Implicit reference access to the internally stored JSON value. No copies
13827
    are made.
13828
13829
    @warning Writing data to the referee of the result yields an undefined
13830
    state.
13831
13832
    @tparam ReferenceType reference type; must be a reference to @ref array_t,
13833
    @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or
13834
    @ref number_float_t. Enforced by static assertion.
13835
13836
    @return reference to the internally stored JSON value if the requested
13837
    reference type @a ReferenceType fits to the JSON value; throws
13838
    type_error.303 otherwise
13839
13840
    @throw type_error.303 in case passed type @a ReferenceType is incompatible
13841
    with the stored JSON value; see example below
13842
13843
    @complexity Constant.
13844
13845
    @liveexample{The example shows several calls to `get_ref()`.,get_ref}
13846
13847
    @since version 1.1.0
13848
    */
13849
    template<typename ReferenceType, typename std::enable_if<
13850
                 std::is_reference<ReferenceType>::value, int>::type = 0>
13851
    ReferenceType get_ref()
13852
    {
13853
        // delegate call to get_ref_impl
13854
        return get_ref_impl<ReferenceType>(*this);
13855
    }
13856
13857
    /*!
13858
    @brief get a reference value (implicit)
13859
    @copydoc get_ref()
13860
    */
13861
    template<typename ReferenceType, typename std::enable_if<
13862
                 std::is_reference<ReferenceType>::value and
13863
                 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
13864
    ReferenceType get_ref() const
13865
    {
13866
        // delegate call to get_ref_impl
13867
        return get_ref_impl<ReferenceType>(*this);
13868
    }
13869
13870
    /*!
13871
    @brief get a value (implicit)
13872
13873
    Implicit type conversion between the JSON value and a compatible value.
13874
    The call is realized by calling @ref get() const.
13875
13876
    @tparam ValueType non-pointer type compatible to the JSON value, for
13877
    instance `int` for JSON integer numbers, `bool` for JSON booleans, or
13878
    `std::vector` types for JSON arrays. The character type of @ref string_t
13879
    as well as an initializer list of this type is excluded to avoid
13880
    ambiguities as these types implicitly convert to `std::string`.
13881
13882
    @return copy of the JSON value, converted to type @a ValueType
13883
13884
    @throw type_error.302 in case passed type @a ValueType is incompatible
13885
    to the JSON value type (e.g., the JSON value is of type boolean, but a
13886
    string is requested); see example below
13887
13888
    @complexity Linear in the size of the JSON value.
13889
13890
    @liveexample{The example below shows several conversions from JSON values
13891
    to other types. There a few things to note: (1) Floating-point numbers can
13892
    be converted to integers\, (2) A JSON array can be converted to a standard
13893
    `std::vector<short>`\, (3) A JSON object can be converted to C++
13894
    associative containers such as `std::unordered_map<std::string\,
13895
    json>`.,operator__ValueType}
13896
13897
    @since version 1.0.0
13898
    */
13899
    template < typename ValueType, typename std::enable_if <
13900
                   not std::is_pointer<ValueType>::value and
13901
                   not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
13902
                   not std::is_same<ValueType, typename string_t::value_type>::value and
13903
                   not detail::is_basic_json<ValueType>::value
13904
#ifndef _MSC_VER  // fix for issue #167 operator<< ambiguity under VS2015
13905
                   and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
13906
#if defined(JSON_HAS_CPP_17) && defined(_MSC_VER) and _MSC_VER <= 1914
13907
                   and not std::is_same<ValueType, typename std::string_view>::value
13908
#endif
13909
#endif
13910
                   , int >::type = 0 >
13911
    operator ValueType() const
13912
    {
13913
        // delegate the call to get<>() const
13914
        return get<ValueType>();
13915
    }
13916
13917
    /// @}
13918
13919
13920
    ////////////////////
13921
    // element access //
13922
    ////////////////////
13923
13924
    /// @name element access
13925
    /// Access to the JSON value.
13926
    /// @{
13927
13928
    /*!
13929
    @brief access specified array element with bounds checking
13930
13931
    Returns a reference to the element at specified location @a idx, with
13932
    bounds checking.
13933
13934
    @param[in] idx  index of the element to access
13935
13936
    @return reference to the element at index @a idx
13937
13938
    @throw type_error.304 if the JSON value is not an array; in this case,
13939
    calling `at` with an index makes no sense. See example below.
13940
    @throw out_of_range.401 if the index @a idx is out of range of the array;
13941
    that is, `idx >= size()`. See example below.
13942
13943
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13944
    changes in the JSON value.
13945
13946
    @complexity Constant.
13947
13948
    @since version 1.0.0
13949
13950
    @liveexample{The example below shows how array elements can be read and
13951
    written using `at()`. It also demonstrates the different exceptions that
13952
    can be thrown.,at__size_type}
13953
    */
13954
    reference at(size_type idx)
13955
    {
13956
        // at only works for arrays
13957
        if (JSON_LIKELY(is_array()))
13958
        {
13959
            JSON_TRY
13960
            {
13961
                return m_value.array->at(idx);
13962
            }
13963
            JSON_CATCH (std::out_of_range&)
13964
            {
13965
                // create better exception explanation
13966
                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
13967
            }
13968
        }
13969
        else
13970
        {
13971
            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
13972
        }
13973
    }
13974
13975
    /*!
13976
    @brief access specified array element with bounds checking
13977
13978
    Returns a const reference to the element at specified location @a idx,
13979
    with bounds checking.
13980
13981
    @param[in] idx  index of the element to access
13982
13983
    @return const reference to the element at index @a idx
13984
13985
    @throw type_error.304 if the JSON value is not an array; in this case,
13986
    calling `at` with an index makes no sense. See example below.
13987
    @throw out_of_range.401 if the index @a idx is out of range of the array;
13988
    that is, `idx >= size()`. See example below.
13989
13990
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13991
    changes in the JSON value.
13992
13993
    @complexity Constant.
13994
13995
    @since version 1.0.0
13996
13997
    @liveexample{The example below shows how array elements can be read using
13998
    `at()`. It also demonstrates the different exceptions that can be thrown.,
13999
    at__size_type_const}
14000
    */
14001
    const_reference at(size_type idx) const
14002
    {
14003
        // at only works for arrays
14004
        if (JSON_LIKELY(is_array()))
14005
        {
14006
            JSON_TRY
14007
            {
14008
                return m_value.array->at(idx);
14009
            }
14010
            JSON_CATCH (std::out_of_range&)
14011
            {
14012
                // create better exception explanation
14013
                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
14014
            }
14015
        }
14016
        else
14017
        {
14018
            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
14019
        }
14020
    }
14021
14022
    /*!
14023
    @brief access specified object element with bounds checking
14024
14025
    Returns a reference to the element at with specified key @a key, with
14026
    bounds checking.
14027
14028
    @param[in] key  key of the element to access
14029
14030
    @return reference to the element at key @a key
14031
14032
    @throw type_error.304 if the JSON value is not an object; in this case,
14033
    calling `at` with a key makes no sense. See example below.
14034
    @throw out_of_range.403 if the key @a key is is not stored in the object;
14035
    that is, `find(key) == end()`. See example below.
14036
14037
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
14038
    changes in the JSON value.
14039
14040
    @complexity Logarithmic in the size of the container.
14041
14042
    @sa @ref operator[](const typename object_t::key_type&) for unchecked
14043
    access by reference
14044
    @sa @ref value() for access by value with a default value
14045
14046
    @since version 1.0.0
14047
14048
    @liveexample{The example below shows how object elements can be read and
14049
    written using `at()`. It also demonstrates the different exceptions that
14050
    can be thrown.,at__object_t_key_type}
14051
    */
14052
    reference at(const typename object_t::key_type& key)
35.2k
14053
    {
35.2k
14054
        // at only works for objects
35.2k
14055
        if (JSON_LIKELY(is_object()))
35.2k
14056
        {
35.2k
14057
            JSON_TRY
35.2k
14058
            {
35.2k
14059
                return m_value.object->at(key);
35.2k
14060
            }
35.2k
14061
            JSON_CATCH (std::out_of_range&)
4
14062
            {
4
14063
                // create better exception explanation
4
14064
                JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
4
14065
            }
35.2k
14066
        }
35.2k
14067
        else
0
14068
        {
0
14069
            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
0
14070
        }
35.2k
14071
    }
14072
14073
    /*!
14074
    @brief access specified object element with bounds checking
14075
14076
    Returns a const reference to the element at with specified key @a key,
14077
    with bounds checking.
14078
14079
    @param[in] key  key of the element to access
14080
14081
    @return const reference to the element at key @a key
14082
14083
    @throw type_error.304 if the JSON value is not an object; in this case,
14084
    calling `at` with a key makes no sense. See example below.
14085
    @throw out_of_range.403 if the key @a key is is not stored in the object;
14086
    that is, `find(key) == end()`. See example below.
14087
14088
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
14089
    changes in the JSON value.
14090
14091
    @complexity Logarithmic in the size of the container.
14092
14093
    @sa @ref operator[](const typename object_t::key_type&) for unchecked
14094
    access by reference
14095
    @sa @ref value() for access by value with a default value
14096
14097
    @since version 1.0.0
14098
14099
    @liveexample{The example below shows how object elements can be read using
14100
    `at()`. It also demonstrates the different exceptions that can be thrown.,
14101
    at__object_t_key_type_const}
14102
    */
14103
    const_reference at(const typename object_t::key_type& key) const
14104
    {
14105
        // at only works for objects
14106
        if (JSON_LIKELY(is_object()))
14107
        {
14108
            JSON_TRY
14109
            {
14110
                return m_value.object->at(key);
14111
            }
14112
            JSON_CATCH (std::out_of_range&)
14113
            {
14114
                // create better exception explanation
14115
                JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
14116
            }
14117
        }
14118
        else
14119
        {
14120
            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
14121
        }
14122
    }
14123
14124
    /*!
14125
    @brief access specified array element
14126
14127
    Returns a reference to the element at specified location @a idx.
14128
14129
    @note If @a idx is beyond the range of the array (i.e., `idx >= size()`),
14130
    then the array is silently filled up with `null` values to make `idx` a
14131
    valid reference to the last stored element.
14132
14133
    @param[in] idx  index of the element to access
14134
14135
    @return reference to the element at index @a idx
14136
14137
    @throw type_error.305 if the JSON value is not an array or null; in that
14138
    cases, using the [] operator with an index makes no sense.
14139
14140
    @complexity Constant if @a idx is in the range of the array. Otherwise
14141
    linear in `idx - size()`.
14142
14143
    @liveexample{The example below shows how array elements can be read and
14144
    written using `[]` operator. Note the addition of `null`
14145
    values.,operatorarray__size_type}
14146
14147
    @since version 1.0.0
14148
    */
14149
    reference operator[](size_type idx)
14150
    {
14151
        // implicitly convert null value to an empty array
14152
        if (is_null())
14153
        {
14154
            m_type = value_t::array;
14155
            m_value.array = create<array_t>();
14156
            assert_invariant();
14157
        }
14158
14159
        // operator[] only works for arrays
14160
        if (JSON_LIKELY(is_array()))
14161
        {
14162
            // fill up array with null values if given idx is outside range
14163
            if (idx >= m_value.array->size())
14164
            {
14165
                m_value.array->insert(m_value.array->end(),
14166
                                      idx - m_value.array->size() + 1,
14167
                                      basic_json());
14168
            }
14169
14170
            return m_value.array->operator[](idx);
14171
        }
14172
14173
        JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
14174
    }
14175
14176
    /*!
14177
    @brief access specified array element
14178
14179
    Returns a const reference to the element at specified location @a idx.
14180
14181
    @param[in] idx  index of the element to access
14182
14183
    @return const reference to the element at index @a idx
14184
14185
    @throw type_error.305 if the JSON value is not an array; in that case,
14186
    using the [] operator with an index makes no sense.
14187
14188
    @complexity Constant.
14189
14190
    @liveexample{The example below shows how array elements can be read using
14191
    the `[]` operator.,operatorarray__size_type_const}
14192
14193
    @since version 1.0.0
14194
    */
14195
    const_reference operator[](size_type idx) const
14196
    {
14197
        // const operator[] only works for arrays
14198
        if (JSON_LIKELY(is_array()))
14199
        {
14200
            return m_value.array->operator[](idx);
14201
        }
14202
14203
        JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
14204
    }
14205
14206
    /*!
14207
    @brief access specified object element
14208
14209
    Returns a reference to the element at with specified key @a key.
14210
14211
    @note If @a key is not found in the object, then it is silently added to
14212
    the object and filled with a `null` value to make `key` a valid reference.
14213
    In case the value was `null` before, it is converted to an object.
14214
14215
    @param[in] key  key of the element to access
14216
14217
    @return reference to the element at key @a key
14218
14219
    @throw type_error.305 if the JSON value is not an object or null; in that
14220
    cases, using the [] operator with a key makes no sense.
14221
14222
    @complexity Logarithmic in the size of the container.
14223
14224
    @liveexample{The example below shows how object elements can be read and
14225
    written using the `[]` operator.,operatorarray__key_type}
14226
14227
    @sa @ref at(const typename object_t::key_type&) for access by reference
14228
    with range checking
14229
    @sa @ref value() for access by value with a default value
14230
14231
    @since version 1.0.0
14232
    */
14233
    reference operator[](const typename object_t::key_type& key)
1.10k
14234
    {
1.10k
14235
        // implicitly convert null value to an empty object
1.10k
14236
        if (is_null())
284
14237
        {
284
14238
            m_type = value_t::object;
284
14239
            m_value.object = create<object_t>();
284
14240
            assert_invariant();
284
14241
        }
1.10k
14242
1.10k
14243
        // operator[] only works for objects
1.10k
14244
        if (JSON_LIKELY(is_object()))
1.10k
14245
        {
1.10k
14246
            return m_value.object->operator[](key);
1.10k
14247
        }
1.10k
14248
0
14249
        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
1.10k
14250
    }
14251
14252
    /*!
14253
    @brief read-only access specified object element
14254
14255
    Returns a const reference to the element at with specified key @a key. No
14256
    bounds checking is performed.
14257
14258
    @warning If the element with key @a key does not exist, the behavior is
14259
    undefined.
14260
14261
    @param[in] key  key of the element to access
14262
14263
    @return const reference to the element at key @a key
14264
14265
    @pre The element with key @a key must exist. **This precondition is
14266
         enforced with an assertion.**
14267
14268
    @throw type_error.305 if the JSON value is not an object; in that case,
14269
    using the [] operator with a key makes no sense.
14270
14271
    @complexity Logarithmic in the size of the container.
14272
14273
    @liveexample{The example below shows how object elements can be read using
14274
    the `[]` operator.,operatorarray__key_type_const}
14275
14276
    @sa @ref at(const typename object_t::key_type&) for access by reference
14277
    with range checking
14278
    @sa @ref value() for access by value with a default value
14279
14280
    @since version 1.0.0
14281
    */
14282
    const_reference operator[](const typename object_t::key_type& key) const
14283
    {
14284
        // const operator[] only works for objects
14285
        if (JSON_LIKELY(is_object()))
14286
        {
14287
            assert(m_value.object->find(key) != m_value.object->end());
14288
            return m_value.object->find(key)->second;
14289
        }
14290
14291
        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
14292
    }
14293
14294
    /*!
14295
    @brief access specified object element
14296
14297
    Returns a reference to the element at with specified key @a key.
14298
14299
    @note If @a key is not found in the object, then it is silently added to
14300
    the object and filled with a `null` value to make `key` a valid reference.
14301
    In case the value was `null` before, it is converted to an object.
14302
14303
    @param[in] key  key of the element to access
14304
14305
    @return reference to the element at key @a key
14306
14307
    @throw type_error.305 if the JSON value is not an object or null; in that
14308
    cases, using the [] operator with a key makes no sense.
14309
14310
    @complexity Logarithmic in the size of the container.
14311
14312
    @liveexample{The example below shows how object elements can be read and
14313
    written using the `[]` operator.,operatorarray__key_type}
14314
14315
    @sa @ref at(const typename object_t::key_type&) for access by reference
14316
    with range checking
14317
    @sa @ref value() for access by value with a default value
14318
14319
    @since version 1.1.0
14320
    */
14321
    template<typename T>
14322
    reference operator[](T* key)
4.99k
14323
    {
4.99k
14324
        // implicitly convert null to object
4.99k
14325
        if (is_null())
972
14326
        {
972
14327
            m_type = value_t::object;
972
14328
            m_value = value_t::object;
972
14329
            assert_invariant();
972
14330
        }
4.99k
14331
4.99k
14332
        // at only works for objects
4.99k
14333
        if (JSON_LIKELY(is_object()))
4.99k
14334
        {
4.99k
14335
            return m_value.object->operator[](key);
4.99k
14336
        }
4.99k
14337
0
14338
        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
4.99k
14339
    }
14340
14341
    /*!
14342
    @brief read-only access specified object element
14343
14344
    Returns a const reference to the element at with specified key @a key. No
14345
    bounds checking is performed.
14346
14347
    @warning If the element with key @a key does not exist, the behavior is
14348
    undefined.
14349
14350
    @param[in] key  key of the element to access
14351
14352
    @return const reference to the element at key @a key
14353
14354
    @pre The element with key @a key must exist. **This precondition is
14355
         enforced with an assertion.**
14356
14357
    @throw type_error.305 if the JSON value is not an object; in that case,
14358
    using the [] operator with a key makes no sense.
14359
14360
    @complexity Logarithmic in the size of the container.
14361
14362
    @liveexample{The example below shows how object elements can be read using
14363
    the `[]` operator.,operatorarray__key_type_const}
14364
14365
    @sa @ref at(const typename object_t::key_type&) for access by reference
14366
    with range checking
14367
    @sa @ref value() for access by value with a default value
14368
14369
    @since version 1.1.0
14370
    */
14371
    template<typename T>
14372
    const_reference operator[](T* key) const
14373
    {
14374
        // at only works for objects
14375
        if (JSON_LIKELY(is_object()))
14376
        {
14377
            assert(m_value.object->find(key) != m_value.object->end());
14378
            return m_value.object->find(key)->second;
14379
        }
14380
14381
        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
14382
    }
14383
14384
    /*!
14385
    @brief access specified object element with default value
14386
14387
    Returns either a copy of an object's element at the specified key @a key
14388
    or a given default value if no element with key @a key exists.
14389
14390
    The function is basically equivalent to executing
14391
    @code {.cpp}
14392
    try {
14393
        return at(key);
14394
    } catch(out_of_range) {
14395
        return default_value;
14396
    }
14397
    @endcode
14398
14399
    @note Unlike @ref at(const typename object_t::key_type&), this function
14400
    does not throw if the given key @a key was not found.
14401
14402
    @note Unlike @ref operator[](const typename object_t::key_type& key), this
14403
    function does not implicitly add an element to the position defined by @a
14404
    key. This function is furthermore also applicable to const objects.
14405
14406
    @param[in] key  key of the element to access
14407
    @param[in] default_value  the value to return if @a key is not found
14408
14409
    @tparam ValueType type compatible to JSON values, for instance `int` for
14410
    JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
14411
    JSON arrays. Note the type of the expected value at @a key and the default
14412
    value @a default_value must be compatible.
14413
14414
    @return copy of the element at key @a key or @a default_value if @a key
14415
    is not found
14416
14417
    @throw type_error.306 if the JSON value is not an object; in that case,
14418
    using `value()` with a key makes no sense.
14419
14420
    @complexity Logarithmic in the size of the container.
14421
14422
    @liveexample{The example below shows how object elements can be queried
14423
    with a default value.,basic_json__value}
14424
14425
    @sa @ref at(const typename object_t::key_type&) for access by reference
14426
    with range checking
14427
    @sa @ref operator[](const typename object_t::key_type&) for unchecked
14428
    access by reference
14429
14430
    @since version 1.0.0
14431
    */
14432
    template<class ValueType, typename std::enable_if<
14433
                 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
14434
    ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
14435
    {
14436
        // at only works for objects
14437
        if (JSON_LIKELY(is_object()))
14438
        {
14439
            // if key is found, return value and given default value otherwise
14440
            const auto it = find(key);
14441
            if (it != end())
14442
            {
14443
                return *it;
14444
            }
14445
14446
            return default_value;
14447
        }
14448
14449
        JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
14450
    }
14451
14452
    /*!
14453
    @brief overload for a default value of type const char*
14454
    @copydoc basic_json::value(const typename object_t::key_type&, ValueType) const
14455
    */
14456
    string_t value(const typename object_t::key_type& key, const char* default_value) const
14457
    {
14458
        return value(key, string_t(default_value));
14459
    }
14460
14461
    /*!
14462
    @brief access specified object element via JSON Pointer with default value
14463
14464
    Returns either a copy of an object's element at the specified key @a key
14465
    or a given default value if no element with key @a key exists.
14466
14467
    The function is basically equivalent to executing
14468
    @code {.cpp}
14469
    try {
14470
        return at(ptr);
14471
    } catch(out_of_range) {
14472
        return default_value;
14473
    }
14474
    @endcode
14475
14476
    @note Unlike @ref at(const json_pointer&), this function does not throw
14477
    if the given key @a key was not found.
14478
14479
    @param[in] ptr  a JSON pointer to the element to access
14480
    @param[in] default_value  the value to return if @a ptr found no value
14481
14482
    @tparam ValueType type compatible to JSON values, for instance `int` for
14483
    JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
14484
    JSON arrays. Note the type of the expected value at @a key and the default
14485
    value @a default_value must be compatible.
14486
14487
    @return copy of the element at key @a key or @a default_value if @a key
14488
    is not found
14489
14490
    @throw type_error.306 if the JSON value is not an object; in that case,
14491
    using `value()` with a key makes no sense.
14492
14493
    @complexity Logarithmic in the size of the container.
14494
14495
    @liveexample{The example below shows how object elements can be queried
14496
    with a default value.,basic_json__value_ptr}
14497
14498
    @sa @ref operator[](const json_pointer&) for unchecked access by reference
14499
14500
    @since version 2.0.2
14501
    */
14502
    template<class ValueType, typename std::enable_if<
14503
                 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
14504
    ValueType value(const json_pointer& ptr, const ValueType& default_value) const
14505
    {
14506
        // at only works for objects
14507
        if (JSON_LIKELY(is_object()))
14508
        {
14509
            // if pointer resolves a value, return it or use default value
14510
            JSON_TRY
14511
            {
14512
                return ptr.get_checked(this);
14513
            }
14514
            JSON_INTERNAL_CATCH (out_of_range&)
14515
            {
14516
                return default_value;
14517
            }
14518
        }
14519
14520
        JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
14521
    }
14522
14523
    /*!
14524
    @brief overload for a default value of type const char*
14525
    @copydoc basic_json::value(const json_pointer&, ValueType) const
14526
    */
14527
    string_t value(const json_pointer& ptr, const char* default_value) const
14528
    {
14529
        return value(ptr, string_t(default_value));
14530
    }
14531
14532
    /*!
14533
    @brief access the first element
14534
14535
    Returns a reference to the first element in the container. For a JSON
14536
    container `c`, the expression `c.front()` is equivalent to `*c.begin()`.
14537
14538
    @return In case of a structured type (array or object), a reference to the
14539
    first element is returned. In case of number, string, or boolean values, a
14540
    reference to the value is returned.
14541
14542
    @complexity Constant.
14543
14544
    @pre The JSON value must not be `null` (would throw `std::out_of_range`)
14545
    or an empty array or object (undefined behavior, **guarded by
14546
    assertions**).
14547
    @post The JSON value remains unchanged.
14548
14549
    @throw invalid_iterator.214 when called on `null` value
14550
14551
    @liveexample{The following code shows an example for `front()`.,front}
14552
14553
    @sa @ref back() -- access the last element
14554
14555
    @since version 1.0.0
14556
    */
14557
    reference front()
14558
    {
14559
        return *begin();
14560
    }
14561
14562
    /*!
14563
    @copydoc basic_json::front()
14564
    */
14565
    const_reference front() const
14566
    {
14567
        return *cbegin();
14568
    }
14569
14570
    /*!
14571
    @brief access the last element
14572
14573
    Returns a reference to the last element in the container. For a JSON
14574
    container `c`, the expression `c.back()` is equivalent to
14575
    @code {.cpp}
14576
    auto tmp = c.end();
14577
    --tmp;
14578
    return *tmp;
14579
    @endcode
14580
14581
    @return In case of a structured type (array or object), a reference to the
14582
    last element is returned. In case of number, string, or boolean values, a
14583
    reference to the value is returned.
14584
14585
    @complexity Constant.
14586
14587
    @pre The JSON value must not be `null` (would throw `std::out_of_range`)
14588
    or an empty array or object (undefined behavior, **guarded by
14589
    assertions**).
14590
    @post The JSON value remains unchanged.
14591
14592
    @throw invalid_iterator.214 when called on a `null` value. See example
14593
    below.
14594
14595
    @liveexample{The following code shows an example for `back()`.,back}
14596
14597
    @sa @ref front() -- access the first element
14598
14599
    @since version 1.0.0
14600
    */
14601
    reference back()
14602
    {
14603
        auto tmp = end();
14604
        --tmp;
14605
        return *tmp;
14606
    }
14607
14608
    /*!
14609
    @copydoc basic_json::back()
14610
    */
14611
    const_reference back() const
14612
    {
14613
        auto tmp = cend();
14614
        --tmp;
14615
        return *tmp;
14616
    }
14617
14618
    /*!
14619
    @brief remove element given an iterator
14620
14621
    Removes the element specified by iterator @a pos. The iterator @a pos must
14622
    be valid and dereferenceable. Thus the `end()` iterator (which is valid,
14623
    but is not dereferenceable) cannot be used as a value for @a pos.
14624
14625
    If called on a primitive type other than `null`, the resulting JSON value
14626
    will be `null`.
14627
14628
    @param[in] pos iterator to the element to remove
14629
    @return Iterator following the last removed element. If the iterator @a
14630
    pos refers to the last element, the `end()` iterator is returned.
14631
14632
    @tparam IteratorType an @ref iterator or @ref const_iterator
14633
14634
    @post Invalidates iterators and references at or after the point of the
14635
    erase, including the `end()` iterator.
14636
14637
    @throw type_error.307 if called on a `null` value; example: `"cannot use
14638
    erase() with null"`
14639
    @throw invalid_iterator.202 if called on an iterator which does not belong
14640
    to the current JSON value; example: `"iterator does not fit current
14641
    value"`
14642
    @throw invalid_iterator.205 if called on a primitive type with invalid
14643
    iterator (i.e., any iterator which is not `begin()`); example: `"iterator
14644
    out of range"`
14645
14646
    @complexity The complexity depends on the type:
14647
    - objects: amortized constant
14648
    - arrays: linear in distance between @a pos and the end of the container
14649
    - strings: linear in the length of the string
14650
    - other types: constant
14651
14652
    @liveexample{The example shows the result of `erase()` for different JSON
14653
    types.,erase__IteratorType}
14654
14655
    @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
14656
    the given range
14657
    @sa @ref erase(const typename object_t::key_type&) -- removes the element
14658
    from an object at the given key
14659
    @sa @ref erase(const size_type) -- removes the element from an array at
14660
    the given index
14661
14662
    @since version 1.0.0
14663
    */
14664
    template<class IteratorType, typename std::enable_if<
14665
                 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
14666
                 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
14667
             = 0>
14668
    IteratorType erase(IteratorType pos)
0
14669
    {
0
14670
        // make sure iterator fits the current value
0
14671
        if (JSON_UNLIKELY(this != pos.m_object))
0
14672
        {
0
14673
            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
0
14674
        }
0
14675
0
14676
        IteratorType result = end();
0
14677
0
14678
        switch (m_type)
0
14679
        {
0
14680
            case value_t::boolean:
0
14681
            case value_t::number_float:
0
14682
            case value_t::number_integer:
0
14683
            case value_t::number_unsigned:
0
14684
            case value_t::string:
0
14685
            {
0
14686
                if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
0
14687
                {
0
14688
                    JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
0
14689
                }
0
14690
0
14691
                if (is_string())
0
14692
                {
0
14693
                    AllocatorType<string_t> alloc;
0
14694
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
0
14695
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
0
14696
                    m_value.string = nullptr;
0
14697
                }
0
14698
0
14699
                m_type = value_t::null;
0
14700
                assert_invariant();
0
14701
                break;
0
14702
            }
0
14703
0
14704
            case value_t::object:
0
14705
            {
0
14706
                result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
0
14707
                break;
0
14708
            }
0
14709
0
14710
            case value_t::array:
0
14711
            {
0
14712
                result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
0
14713
                break;
0
14714
            }
0
14715
0
14716
            default:
0
14717
                JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
0
14718
        }
0
14719
0
14720
        return result;
0
14721
    }
14722
14723
    /*!
14724
    @brief remove elements given an iterator range
14725
14726
    Removes the element specified by the range `[first; last)`. The iterator
14727
    @a first does not need to be dereferenceable if `first == last`: erasing
14728
    an empty range is a no-op.
14729
14730
    If called on a primitive type other than `null`, the resulting JSON value
14731
    will be `null`.
14732
14733
    @param[in] first iterator to the beginning of the range to remove
14734
    @param[in] last iterator past the end of the range to remove
14735
    @return Iterator following the last removed element. If the iterator @a
14736
    second refers to the last element, the `end()` iterator is returned.
14737
14738
    @tparam IteratorType an @ref iterator or @ref const_iterator
14739
14740
    @post Invalidates iterators and references at or after the point of the
14741
    erase, including the `end()` iterator.
14742
14743
    @throw type_error.307 if called on a `null` value; example: `"cannot use
14744
    erase() with null"`
14745
    @throw invalid_iterator.203 if called on iterators which does not belong
14746
    to the current JSON value; example: `"iterators do not fit current value"`
14747
    @throw invalid_iterator.204 if called on a primitive type with invalid
14748
    iterators (i.e., if `first != begin()` and `last != end()`); example:
14749
    `"iterators out of range"`
14750
14751
    @complexity The complexity depends on the type:
14752
    - objects: `log(size()) + std::distance(first, last)`
14753
    - arrays: linear in the distance between @a first and @a last, plus linear
14754
      in the distance between @a last and end of the container
14755
    - strings: linear in the length of the string
14756
    - other types: constant
14757
14758
    @liveexample{The example shows the result of `erase()` for different JSON
14759
    types.,erase__IteratorType_IteratorType}
14760
14761
    @sa @ref erase(IteratorType) -- removes the element at a given position
14762
    @sa @ref erase(const typename object_t::key_type&) -- removes the element
14763
    from an object at the given key
14764
    @sa @ref erase(const size_type) -- removes the element from an array at
14765
    the given index
14766
14767
    @since version 1.0.0
14768
    */
14769
    template<class IteratorType, typename std::enable_if<
14770
                 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
14771
                 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
14772
             = 0>
14773
    IteratorType erase(IteratorType first, IteratorType last)
14774
    {
14775
        // make sure iterator fits the current value
14776
        if (JSON_UNLIKELY(this != first.m_object or this != last.m_object))
14777
        {
14778
            JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
14779
        }
14780
14781
        IteratorType result = end();
14782
14783
        switch (m_type)
14784
        {
14785
            case value_t::boolean:
14786
            case value_t::number_float:
14787
            case value_t::number_integer:
14788
            case value_t::number_unsigned:
14789
            case value_t::string:
14790
            {
14791
                if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin()
14792
                                or not last.m_it.primitive_iterator.is_end()))
14793
                {
14794
                    JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
14795
                }
14796
14797
                if (is_string())
14798
                {
14799
                    AllocatorType<string_t> alloc;
14800
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
14801
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
14802
                    m_value.string = nullptr;
14803
                }
14804
14805
                m_type = value_t::null;
14806
                assert_invariant();
14807
                break;
14808
            }
14809
14810
            case value_t::object:
14811
            {
14812
                result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
14813
                                              last.m_it.object_iterator);
14814
                break;
14815
            }
14816
14817
            case value_t::array:
14818
            {
14819
                result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
14820
                                             last.m_it.array_iterator);
14821
                break;
14822
            }
14823
14824
            default:
14825
                JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
14826
        }
14827
14828
        return result;
14829
    }
14830
14831
    /*!
14832
    @brief remove element from a JSON object given a key
14833
14834
    Removes elements from a JSON object with the key value @a key.
14835
14836
    @param[in] key value of the elements to remove
14837
14838
    @return Number of elements removed. If @a ObjectType is the default
14839
    `std::map` type, the return value will always be `0` (@a key was not
14840
    found) or `1` (@a key was found).
14841
14842
    @post References and iterators to the erased elements are invalidated.
14843
    Other references and iterators are not affected.
14844
14845
    @throw type_error.307 when called on a type other than JSON object;
14846
    example: `"cannot use erase() with null"`
14847
14848
    @complexity `log(size()) + count(key)`
14849
14850
    @liveexample{The example shows the effect of `erase()`.,erase__key_type}
14851
14852
    @sa @ref erase(IteratorType) -- removes the element at a given position
14853
    @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
14854
    the given range
14855
    @sa @ref erase(const size_type) -- removes the element from an array at
14856
    the given index
14857
14858
    @since version 1.0.0
14859
    */
14860
    size_type erase(const typename object_t::key_type& key)
14861
    {
14862
        // this erase only works for objects
14863
        if (JSON_LIKELY(is_object()))
14864
        {
14865
            return m_value.object->erase(key);
14866
        }
14867
14868
        JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
14869
    }
14870
14871
    /*!
14872
    @brief remove element from a JSON array given an index
14873
14874
    Removes element from a JSON array at the index @a idx.
14875
14876
    @param[in] idx index of the element to remove
14877
14878
    @throw type_error.307 when called on a type other than JSON object;
14879
    example: `"cannot use erase() with null"`
14880
    @throw out_of_range.401 when `idx >= size()`; example: `"array index 17
14881
    is out of range"`
14882
14883
    @complexity Linear in distance between @a idx and the end of the container.
14884
14885
    @liveexample{The example shows the effect of `erase()`.,erase__size_type}
14886
14887
    @sa @ref erase(IteratorType) -- removes the element at a given position
14888
    @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
14889
    the given range
14890
    @sa @ref erase(const typename object_t::key_type&) -- removes the element
14891
    from an object at the given key
14892
14893
    @since version 1.0.0
14894
    */
14895
    void erase(const size_type idx)
14896
    {
14897
        // this erase only works for arrays
14898
        if (JSON_LIKELY(is_array()))
14899
        {
14900
            if (JSON_UNLIKELY(idx >= size()))
14901
            {
14902
                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
14903
            }
14904
14905
            m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
14906
        }
14907
        else
14908
        {
14909
            JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
14910
        }
14911
    }
14912
14913
    /// @}
14914
14915
14916
    ////////////
14917
    // lookup //
14918
    ////////////
14919
14920
    /// @name lookup
14921
    /// @{
14922
14923
    /*!
14924
    @brief find an element in a JSON object
14925
14926
    Finds an element in a JSON object with key equivalent to @a key. If the
14927
    element is not found or the JSON value is not an object, end() is
14928
    returned.
14929
14930
    @note This method always returns @ref end() when executed on a JSON type
14931
          that is not an object.
14932
14933
    @param[in] key key value of the element to search for.
14934
14935
    @return Iterator to an element with key equivalent to @a key. If no such
14936
    element is found or the JSON value is not an object, past-the-end (see
14937
    @ref end()) iterator is returned.
14938
14939
    @complexity Logarithmic in the size of the JSON object.
14940
14941
    @liveexample{The example shows how `find()` is used.,find__key_type}
14942
14943
    @since version 1.0.0
14944
    */
14945
    template<typename KeyT>
14946
    iterator find(KeyT&& key)
60
14947
    {
60
14948
        auto result = end();
60
14949
60
14950
        if (is_object())
56
14951
        {
56
14952
            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
56
14953
        }
60
14954
60
14955
        return result;
60
14956
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE4findIRA9_KcEENS_6detail9iter_implISA_EEOT_
52
14947
    {
52
14948
        auto result = end();
52
14949
52
14950
        if (is_object())
48
14951
        {
48
14952
            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
48
14953
        }
52
14954
52
14955
        return result;
52
14956
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbxydSaNS_14adl_serializerEE4findIRA15_KcEENS_6detail9iter_implISA_EEOT_
8
14947
    {
8
14948
        auto result = end();
8
14949
8
14950
        if (is_object())
8
14951
        {
8
14952
            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
8
14953
        }
8
14954
8
14955
        return result;
8
14956
    }
14957
14958
    /*!
14959
    @brief find an element in a JSON object
14960
    @copydoc find(KeyT&&)
14961
    */
14962
    template<typename KeyT>
14963
    const_iterator find(KeyT&& key) const
14964
    {
14965
        auto result = cend();
14966
14967
        if (is_object())
14968
        {
14969
            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
14970
        }
14971
14972
        return result;
14973
    }
14974
14975
    /*!
14976
    @brief returns the number of occurrences of a key in a JSON object
14977
14978
    Returns the number of elements with key @a key. If ObjectType is the
14979
    default `std::map` type, the return value will always be `0` (@a key was
14980
    not found) or `1` (@a key was found).
14981
14982
    @note This method always returns `0` when executed on a JSON type that is
14983
          not an object.
14984
14985
    @param[in] key key value of the element to count
14986
14987
    @return Number of elements with key @a key. If the JSON value is not an
14988
    object, the return value will be `0`.
14989
14990
    @complexity Logarithmic in the size of the JSON object.
14991
14992
    @liveexample{The example shows how `count()` is used.,count}
14993
14994
    @since version 1.0.0
14995
    */
14996
    template<typename KeyT>
14997
    size_type count(KeyT&& key) const
14998
    {
14999
        // return 0 for all nonobject types
15000
        return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
15001
    }
15002
15003
    /// @}
15004
15005
15006
    ///////////////
15007
    // iterators //
15008
    ///////////////
15009
15010
    /// @name iterators
15011
    /// @{
15012
15013
    /*!
15014
    @brief returns an iterator to the first element
15015
15016
    Returns an iterator to the first element.
15017
15018
    @image html range-begin-end.svg "Illustration from cppreference.com"
15019
15020
    @return iterator to the first element
15021
15022
    @complexity Constant.
15023
15024
    @requirement This function helps `basic_json` satisfying the
15025
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15026
    requirements:
15027
    - The complexity is constant.
15028
15029
    @liveexample{The following code shows an example for `begin()`.,begin}
15030
15031
    @sa @ref cbegin() -- returns a const iterator to the beginning
15032
    @sa @ref end() -- returns an iterator to the end
15033
    @sa @ref cend() -- returns a const iterator to the end
15034
15035
    @since version 1.0.0
15036
    */
15037
    iterator begin() noexcept
1.61k
15038
    {
1.61k
15039
        iterator result(this);
1.61k
15040
        result.set_begin();
1.61k
15041
        return result;
1.61k
15042
    }
15043
15044
    /*!
15045
    @copydoc basic_json::cbegin()
15046
    */
15047
    const_iterator begin() const noexcept
15048
    {
15049
        return cbegin();
15050
    }
15051
15052
    /*!
15053
    @brief returns a const iterator to the first element
15054
15055
    Returns a const iterator to the first element.
15056
15057
    @image html range-begin-end.svg "Illustration from cppreference.com"
15058
15059
    @return const iterator to the first element
15060
15061
    @complexity Constant.
15062
15063
    @requirement This function helps `basic_json` satisfying the
15064
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15065
    requirements:
15066
    - The complexity is constant.
15067
    - Has the semantics of `const_cast<const basic_json&>(*this).begin()`.
15068
15069
    @liveexample{The following code shows an example for `cbegin()`.,cbegin}
15070
15071
    @sa @ref begin() -- returns an iterator to the beginning
15072
    @sa @ref end() -- returns an iterator to the end
15073
    @sa @ref cend() -- returns a const iterator to the end
15074
15075
    @since version 1.0.0
15076
    */
15077
    const_iterator cbegin() const noexcept
15078
    {
15079
        const_iterator result(this);
15080
        result.set_begin();
15081
        return result;
15082
    }
15083
15084
    /*!
15085
    @brief returns an iterator to one past the last element
15086
15087
    Returns an iterator to one past the last element.
15088
15089
    @image html range-begin-end.svg "Illustration from cppreference.com"
15090
15091
    @return iterator one past the last element
15092
15093
    @complexity Constant.
15094
15095
    @requirement This function helps `basic_json` satisfying the
15096
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15097
    requirements:
15098
    - The complexity is constant.
15099
15100
    @liveexample{The following code shows an example for `end()`.,end}
15101
15102
    @sa @ref cend() -- returns a const iterator to the end
15103
    @sa @ref begin() -- returns an iterator to the beginning
15104
    @sa @ref cbegin() -- returns a const iterator to the beginning
15105
15106
    @since version 1.0.0
15107
    */
15108
    iterator end() noexcept
5.44k
15109
    {
5.44k
15110
        iterator result(this);
5.44k
15111
        result.set_end();
5.44k
15112
        return result;
5.44k
15113
    }
15114
15115
    /*!
15116
    @copydoc basic_json::cend()
15117
    */
15118
    const_iterator end() const noexcept
15119
    {
15120
        return cend();
15121
    }
15122
15123
    /*!
15124
    @brief returns a const iterator to one past the last element
15125
15126
    Returns a const iterator to one past the last element.
15127
15128
    @image html range-begin-end.svg "Illustration from cppreference.com"
15129
15130
    @return const iterator one past the last element
15131
15132
    @complexity Constant.
15133
15134
    @requirement This function helps `basic_json` satisfying the
15135
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15136
    requirements:
15137
    - The complexity is constant.
15138
    - Has the semantics of `const_cast<const basic_json&>(*this).end()`.
15139
15140
    @liveexample{The following code shows an example for `cend()`.,cend}
15141
15142
    @sa @ref end() -- returns an iterator to the end
15143
    @sa @ref begin() -- returns an iterator to the beginning
15144
    @sa @ref cbegin() -- returns a const iterator to the beginning
15145
15146
    @since version 1.0.0
15147
    */
15148
    const_iterator cend() const noexcept
15149
    {
15150
        const_iterator result(this);
15151
        result.set_end();
15152
        return result;
15153
    }
15154
15155
    /*!
15156
    @brief returns an iterator to the reverse-beginning
15157
15158
    Returns an iterator to the reverse-beginning; that is, the last element.
15159
15160
    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
15161
15162
    @complexity Constant.
15163
15164
    @requirement This function helps `basic_json` satisfying the
15165
    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
15166
    requirements:
15167
    - The complexity is constant.
15168
    - Has the semantics of `reverse_iterator(end())`.
15169
15170
    @liveexample{The following code shows an example for `rbegin()`.,rbegin}
15171
15172
    @sa @ref crbegin() -- returns a const reverse iterator to the beginning
15173
    @sa @ref rend() -- returns a reverse iterator to the end
15174
    @sa @ref crend() -- returns a const reverse iterator to the end
15175
15176
    @since version 1.0.0
15177
    */
15178
    reverse_iterator rbegin() noexcept
15179
    {
15180
        return reverse_iterator(end());
15181
    }
15182
15183
    /*!
15184
    @copydoc basic_json::crbegin()
15185
    */
15186
    const_reverse_iterator rbegin() const noexcept
15187
    {
15188
        return crbegin();
15189
    }
15190
15191
    /*!
15192
    @brief returns an iterator to the reverse-end
15193
15194
    Returns an iterator to the reverse-end; that is, one before the first
15195
    element.
15196
15197
    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
15198
15199
    @complexity Constant.
15200
15201
    @requirement This function helps `basic_json` satisfying the
15202
    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
15203
    requirements:
15204
    - The complexity is constant.
15205
    - Has the semantics of `reverse_iterator(begin())`.
15206
15207
    @liveexample{The following code shows an example for `rend()`.,rend}
15208
15209
    @sa @ref crend() -- returns a const reverse iterator to the end
15210
    @sa @ref rbegin() -- returns a reverse iterator to the beginning
15211
    @sa @ref crbegin() -- returns a const reverse iterator to the beginning
15212
15213
    @since version 1.0.0
15214
    */
15215
    reverse_iterator rend() noexcept
15216
    {
15217
        return reverse_iterator(begin());
15218
    }
15219
15220
    /*!
15221
    @copydoc basic_json::crend()
15222
    */
15223
    const_reverse_iterator rend() const noexcept
15224
    {
15225
        return crend();
15226
    }
15227
15228
    /*!
15229
    @brief returns a const reverse iterator to the last element
15230
15231
    Returns a const iterator to the reverse-beginning; that is, the last
15232
    element.
15233
15234
    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
15235
15236
    @complexity Constant.
15237
15238
    @requirement This function helps `basic_json` satisfying the
15239
    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
15240
    requirements:
15241
    - The complexity is constant.
15242
    - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.
15243
15244
    @liveexample{The following code shows an example for `crbegin()`.,crbegin}
15245
15246
    @sa @ref rbegin() -- returns a reverse iterator to the beginning
15247
    @sa @ref rend() -- returns a reverse iterator to the end
15248
    @sa @ref crend() -- returns a const reverse iterator to the end
15249
15250
    @since version 1.0.0
15251
    */
15252
    const_reverse_iterator crbegin() const noexcept
15253
    {
15254
        return const_reverse_iterator(cend());
15255
    }
15256
15257
    /*!
15258
    @brief returns a const reverse iterator to one before the first
15259
15260
    Returns a const reverse iterator to the reverse-end; that is, one before
15261
    the first element.
15262
15263
    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
15264
15265
    @complexity Constant.
15266
15267
    @requirement This function helps `basic_json` satisfying the
15268
    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
15269
    requirements:
15270
    - The complexity is constant.
15271
    - Has the semantics of `const_cast<const basic_json&>(*this).rend()`.
15272
15273
    @liveexample{The following code shows an example for `crend()`.,crend}
15274
15275
    @sa @ref rend() -- returns a reverse iterator to the end
15276
    @sa @ref rbegin() -- returns a reverse iterator to the beginning
15277
    @sa @ref crbegin() -- returns a const reverse iterator to the beginning
15278
15279
    @since version 1.0.0
15280
    */
15281
    const_reverse_iterator crend() const noexcept
15282
    {
15283
        return const_reverse_iterator(cbegin());
15284
    }
15285
15286
  public:
15287
    /*!
15288
    @brief wrapper to access iterator member functions in range-based for
15289
15290
    This function allows to access @ref iterator::key() and @ref
15291
    iterator::value() during range-based for loops. In these loops, a
15292
    reference to the JSON values is returned, so there is no access to the
15293
    underlying iterator.
15294
15295
    For loop without iterator_wrapper:
15296
15297
    @code{cpp}
15298
    for (auto it = j_object.begin(); it != j_object.end(); ++it)
15299
    {
15300
        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
15301
    }
15302
    @endcode
15303
15304
    Range-based for loop without iterator proxy:
15305
15306
    @code{cpp}
15307
    for (auto it : j_object)
15308
    {
15309
        // "it" is of type json::reference and has no key() member
15310
        std::cout << "value: " << it << '\n';
15311
    }
15312
    @endcode
15313
15314
    Range-based for loop with iterator proxy:
15315
15316
    @code{cpp}
15317
    for (auto it : json::iterator_wrapper(j_object))
15318
    {
15319
        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
15320
    }
15321
    @endcode
15322
15323
    @note When iterating over an array, `key()` will return the index of the
15324
          element as string (see example).
15325
15326
    @param[in] ref  reference to a JSON value
15327
    @return iteration proxy object wrapping @a ref with an interface to use in
15328
            range-based for loops
15329
15330
    @liveexample{The following code shows how the wrapper is used,iterator_wrapper}
15331
15332
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
15333
    changes in the JSON value.
15334
15335
    @complexity Constant.
15336
15337
    @note The name of this function is not yet final and may change in the
15338
    future.
15339
15340
    @deprecated This stream operator is deprecated and will be removed in
15341
                future 4.0.0 of the library. Please use @ref items() instead;
15342
                that is, replace `json::iterator_wrapper(j)` with `j.items()`.
15343
    */
15344
    JSON_DEPRECATED
15345
    static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
15346
    {
15347
        return ref.items();
15348
    }
15349
15350
    /*!
15351
    @copydoc iterator_wrapper(reference)
15352
    */
15353
    JSON_DEPRECATED
15354
    static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
15355
    {
15356
        return ref.items();
15357
    }
15358
15359
    /*!
15360
    @brief helper to access iterator member functions in range-based for
15361
15362
    This function allows to access @ref iterator::key() and @ref
15363
    iterator::value() during range-based for loops. In these loops, a
15364
    reference to the JSON values is returned, so there is no access to the
15365
    underlying iterator.
15366
15367
    For loop without `items()` function:
15368
15369
    @code{cpp}
15370
    for (auto it = j_object.begin(); it != j_object.end(); ++it)
15371
    {
15372
        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
15373
    }
15374
    @endcode
15375
15376
    Range-based for loop without `items()` function:
15377
15378
    @code{cpp}
15379
    for (auto it : j_object)
15380
    {
15381
        // "it" is of type json::reference and has no key() member
15382
        std::cout << "value: " << it << '\n';
15383
    }
15384
    @endcode
15385
15386
    Range-based for loop with `items()` function:
15387
15388
    @code{cpp}
15389
    for (auto it : j_object.items())
15390
    {
15391
        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
15392
    }
15393
    @endcode
15394
15395
    @note When iterating over an array, `key()` will return the index of the
15396
          element as string (see example). For primitive types (e.g., numbers),
15397
          `key()` returns an empty string.
15398
15399
    @return iteration proxy object wrapping @a ref with an interface to use in
15400
            range-based for loops
15401
15402
    @liveexample{The following code shows how the function is used.,items}
15403
15404
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
15405
    changes in the JSON value.
15406
15407
    @complexity Constant.
15408
15409
    @since version 3.1.0.
15410
    */
15411
    iteration_proxy<iterator> items() noexcept
15412
    {
15413
        return iteration_proxy<iterator>(*this);
15414
    }
15415
15416
    /*!
15417
    @copydoc items()
15418
    */
15419
    iteration_proxy<const_iterator> items() const noexcept
15420
    {
15421
        return iteration_proxy<const_iterator>(*this);
15422
    }
15423
15424
    /// @}
15425
15426
15427
    //////////////
15428
    // capacity //
15429
    //////////////
15430
15431
    /// @name capacity
15432
    /// @{
15433
15434
    /*!
15435
    @brief checks whether the container is empty.
15436
15437
    Checks if a JSON value has no elements (i.e. whether its @ref size is `0`).
15438
15439
    @return The return value depends on the different types and is
15440
            defined as follows:
15441
            Value type  | return value
15442
            ----------- | -------------
15443
            null        | `true`
15444
            boolean     | `false`
15445
            string      | `false`
15446
            number      | `false`
15447
            object      | result of function `object_t::empty()`
15448
            array       | result of function `array_t::empty()`
15449
15450
    @liveexample{The following code uses `empty()` to check if a JSON
15451
    object contains any elements.,empty}
15452
15453
    @complexity Constant, as long as @ref array_t and @ref object_t satisfy
15454
    the Container concept; that is, their `empty()` functions have constant
15455
    complexity.
15456
15457
    @iterators No changes.
15458
15459
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
15460
15461
    @note This function does not return whether a string stored as JSON value
15462
    is empty - it returns whether the JSON container itself is empty which is
15463
    false in the case of a string.
15464
15465
    @requirement This function helps `basic_json` satisfying the
15466
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15467
    requirements:
15468
    - The complexity is constant.
15469
    - Has the semantics of `begin() == end()`.
15470
15471
    @sa @ref size() -- returns the number of elements
15472
15473
    @since version 1.0.0
15474
    */
15475
    bool empty() const noexcept
15476
    {
15477
        switch (m_type)
15478
        {
15479
            case value_t::null:
15480
            {
15481
                // null values are empty
15482
                return true;
15483
            }
15484
15485
            case value_t::array:
15486
            {
15487
                // delegate call to array_t::empty()
15488
                return m_value.array->empty();
15489
            }
15490
15491
            case value_t::object:
15492
            {
15493
                // delegate call to object_t::empty()
15494
                return m_value.object->empty();
15495
            }
15496
15497
            default:
15498
            {
15499
                // all other types are nonempty
15500
                return false;
15501
            }
15502
        }
15503
    }
15504
15505
    /*!
15506
    @brief returns the number of elements
15507
15508
    Returns the number of elements in a JSON value.
15509
15510
    @return The return value depends on the different types and is
15511
            defined as follows:
15512
            Value type  | return value
15513
            ----------- | -------------
15514
            null        | `0`
15515
            boolean     | `1`
15516
            string      | `1`
15517
            number      | `1`
15518
            object      | result of function object_t::size()
15519
            array       | result of function array_t::size()
15520
15521
    @liveexample{The following code calls `size()` on the different value
15522
    types.,size}
15523
15524
    @complexity Constant, as long as @ref array_t and @ref object_t satisfy
15525
    the Container concept; that is, their size() functions have constant
15526
    complexity.
15527
15528
    @iterators No changes.
15529
15530
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
15531
15532
    @note This function does not return the length of a string stored as JSON
15533
    value - it returns the number of elements in the JSON value which is 1 in
15534
    the case of a string.
15535
15536
    @requirement This function helps `basic_json` satisfying the
15537
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15538
    requirements:
15539
    - The complexity is constant.
15540
    - Has the semantics of `std::distance(begin(), end())`.
15541
15542
    @sa @ref empty() -- checks whether the container is empty
15543
    @sa @ref max_size() -- returns the maximal number of elements
15544
15545
    @since version 1.0.0
15546
    */
15547
    size_type size() const noexcept
132
15548
    {
0
15549
        switch (m_type)
0
15550
        {
52
15551
            case value_t::null:
52
15552
            {
52
15553
                // null values are empty
52
15554
                return 0;
52
15555
            }
52
15556
80
15557
            case value_t::array:
80
15558
            {
80
15559
                // delegate call to array_t::size()
80
15560
                return m_value.array->size();
52
15561
            }
52
15562
0
15563
            case value_t::object:
0
15564
            {
0
15565
                // delegate call to object_t::size()
0
15566
                return m_value.object->size();
52
15567
            }
52
15568
0
15569
            default:
0
15570
            {
0
15571
                // all other types have size 1
0
15572
                return 1;
52
15573
            }
0
15574
        }
132
15575
    }
15576
15577
    /*!
15578
    @brief returns the maximum possible number of elements
15579
15580
    Returns the maximum number of elements a JSON value is able to hold due to
15581
    system or library implementation limitations, i.e. `std::distance(begin(),
15582
    end())` for the JSON value.
15583
15584
    @return The return value depends on the different types and is
15585
            defined as follows:
15586
            Value type  | return value
15587
            ----------- | -------------
15588
            null        | `0` (same as `size()`)
15589
            boolean     | `1` (same as `size()`)
15590
            string      | `1` (same as `size()`)
15591
            number      | `1` (same as `size()`)
15592
            object      | result of function `object_t::max_size()`
15593
            array       | result of function `array_t::max_size()`
15594
15595
    @liveexample{The following code calls `max_size()` on the different value
15596
    types. Note the output is implementation specific.,max_size}
15597
15598
    @complexity Constant, as long as @ref array_t and @ref object_t satisfy
15599
    the Container concept; that is, their `max_size()` functions have constant
15600
    complexity.
15601
15602
    @iterators No changes.
15603
15604
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
15605
15606
    @requirement This function helps `basic_json` satisfying the
15607
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15608
    requirements:
15609
    - The complexity is constant.
15610
    - Has the semantics of returning `b.size()` where `b` is the largest
15611
      possible JSON value.
15612
15613
    @sa @ref size() -- returns the number of elements
15614
15615
    @since version 1.0.0
15616
    */
15617
    size_type max_size() const noexcept
0
15618
    {
0
15619
        switch (m_type)
0
15620
        {
0
15621
            case value_t::array:
0
15622
            {
0
15623
                // delegate call to array_t::max_size()
0
15624
                return m_value.array->max_size();
0
15625
            }
0
15626
0
15627
            case value_t::object:
0
15628
            {
0
15629
                // delegate call to object_t::max_size()
0
15630
                return m_value.object->max_size();
0
15631
            }
0
15632
0
15633
            default:
0
15634
            {
0
15635
                // all other types have max_size() == size()
0
15636
                return size();
0
15637
            }
0
15638
        }
0
15639
    }
15640
15641
    /// @}
15642
15643
15644
    ///////////////
15645
    // modifiers //
15646
    ///////////////
15647
15648
    /// @name modifiers
15649
    /// @{
15650
15651
    /*!
15652
    @brief clears the contents
15653
15654
    Clears the content of a JSON value and resets it to the default value as
15655
    if @ref basic_json(value_t) would have been called with the current value
15656
    type from @ref type():
15657
15658
    Value type  | initial value
15659
    ----------- | -------------
15660
    null        | `null`
15661
    boolean     | `false`
15662
    string      | `""`
15663
    number      | `0`
15664
    object      | `{}`
15665
    array       | `[]`
15666
15667
    @post Has the same effect as calling
15668
    @code {.cpp}
15669
    *this = basic_json(type());
15670
    @endcode
15671
15672
    @liveexample{The example below shows the effect of `clear()` to different
15673
    JSON types.,clear}
15674
15675
    @complexity Linear in the size of the JSON value.
15676
15677
    @iterators All iterators, pointers and references related to this container
15678
               are invalidated.
15679
15680
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
15681
15682
    @sa @ref basic_json(value_t) -- constructor that creates an object with the
15683
        same value than calling `clear()`
15684
15685
    @since version 1.0.0
15686
    */
15687
    void clear() noexcept
15688
    {
15689
        switch (m_type)
15690
        {
15691
            case value_t::number_integer:
15692
            {
15693
                m_value.number_integer = 0;
15694
                break;
15695
            }
15696
15697
            case value_t::number_unsigned:
15698
            {
15699
                m_value.number_unsigned = 0;
15700
                break;
15701
            }
15702
15703
            case value_t::number_float:
15704
            {
15705
                m_value.number_float = 0.0;
15706
                break;
15707
            }
15708
15709
            case value_t::boolean:
15710
            {
15711
                m_value.boolean = false;
15712
                break;
15713
            }
15714
15715
            case value_t::string:
15716
            {
15717
                m_value.string->clear();
15718
                break;
15719
            }
15720
15721
            case value_t::array:
15722
            {
15723
                m_value.array->clear();
15724
                break;
15725
            }
15726
15727
            case value_t::object:
15728
            {
15729
                m_value.object->clear();
15730
                break;
15731
            }
15732
15733
            default:
15734
                break;
15735
        }
15736
    }
15737
15738
    /*!
15739
    @brief add an object to an array
15740
15741
    Appends the given element @a val to the end of the JSON value. If the
15742
    function is called on a JSON null value, an empty array is created before
15743
    appending @a val.
15744
15745
    @param[in] val the value to add to the JSON array
15746
15747
    @throw type_error.308 when called on a type other than JSON array or
15748
    null; example: `"cannot use push_back() with number"`
15749
15750
    @complexity Amortized constant.
15751
15752
    @liveexample{The example shows how `push_back()` and `+=` can be used to
15753
    add elements to a JSON array. Note how the `null` value was silently
15754
    converted to a JSON array.,push_back}
15755
15756
    @since version 1.0.0
15757
    */
15758
    void push_back(basic_json&& val)
15759
    {
15760
        // push_back only works for null objects or arrays
15761
        if (JSON_UNLIKELY(not(is_null() or is_array())))
15762
        {
15763
            JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
15764
        }
15765
15766
        // transform null object into an array
15767
        if (is_null())
15768
        {
15769
            m_type = value_t::array;
15770
            m_value = value_t::array;
15771
            assert_invariant();
15772
        }
15773
15774
        // add element to array (move semantics)
15775
        m_value.array->push_back(std::move(val));
15776
        // invalidate object
15777
        val.m_type = value_t::null;
15778
    }
15779
15780
    /*!
15781
    @brief add an object to an array
15782
    @copydoc push_back(basic_json&&)
15783
    */
15784
    reference operator+=(basic_json&& val)
15785
    {
15786
        push_back(std::move(val));
15787
        return *this;
15788
    }
15789
15790
    /*!
15791
    @brief add an object to an array
15792
    @copydoc push_back(basic_json&&)
15793
    */
15794
    void push_back(const basic_json& val)
15795
    {
15796
        // push_back only works for null objects or arrays
15797
        if (JSON_UNLIKELY(not(is_null() or is_array())))
15798
        {
15799
            JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
15800
        }
15801
15802
        // transform null object into an array
15803
        if (is_null())
15804
        {
15805
            m_type = value_t::array;
15806
            m_value = value_t::array;
15807
            assert_invariant();
15808
        }
15809
15810
        // add element to array
15811
        m_value.array->push_back(val);
15812
    }
15813
15814
    /*!
15815
    @brief add an object to an array
15816
    @copydoc push_back(basic_json&&)
15817
    */
15818
    reference operator+=(const basic_json& val)
15819
    {
15820
        push_back(val);
15821
        return *this;
15822
    }
15823
15824
    /*!
15825
    @brief add an object to an object
15826
15827
    Inserts the given element @a val to the JSON object. If the function is
15828
    called on a JSON null value, an empty object is created before inserting
15829
    @a val.
15830
15831
    @param[in] val the value to add to the JSON object
15832
15833
    @throw type_error.308 when called on a type other than JSON object or
15834
    null; example: `"cannot use push_back() with number"`
15835
15836
    @complexity Logarithmic in the size of the container, O(log(`size()`)).
15837
15838
    @liveexample{The example shows how `push_back()` and `+=` can be used to
15839
    add elements to a JSON object. Note how the `null` value was silently
15840
    converted to a JSON object.,push_back__object_t__value}
15841
15842
    @since version 1.0.0
15843
    */
15844
    void push_back(const typename object_t::value_type& val)
15845
    {
15846
        // push_back only works for null objects or objects
15847
        if (JSON_UNLIKELY(not(is_null() or is_object())))
15848
        {
15849
            JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
15850
        }
15851
15852
        // transform null object into an object
15853
        if (is_null())
15854
        {
15855
            m_type = value_t::object;
15856
            m_value = value_t::object;
15857
            assert_invariant();
15858
        }
15859
15860
        // add element to array
15861
        m_value.object->insert(val);
15862
    }
15863
15864
    /*!
15865
    @brief add an object to an object
15866
    @copydoc push_back(const typename object_t::value_type&)
15867
    */
15868
    reference operator+=(const typename object_t::value_type& val)
15869
    {
15870
        push_back(val);
15871
        return *this;
15872
    }
15873
15874
    /*!
15875
    @brief add an object to an object
15876
15877
    This function allows to use `push_back` with an initializer list. In case
15878
15879
    1. the current value is an object,
15880
    2. the initializer list @a init contains only two elements, and
15881
    3. the first element of @a init is a string,
15882
15883
    @a init is converted into an object element and added using
15884
    @ref push_back(const typename object_t::value_type&). Otherwise, @a init
15885
    is converted to a JSON value and added using @ref push_back(basic_json&&).
15886
15887
    @param[in] init  an initializer list
15888
15889
    @complexity Linear in the size of the initializer list @a init.
15890
15891
    @note This function is required to resolve an ambiguous overload error,
15892
          because pairs like `{"key", "value"}` can be both interpreted as
15893
          `object_t::value_type` or `std::initializer_list<basic_json>`, see
15894
          https://github.com/nlohmann/json/issues/235 for more information.
15895
15896
    @liveexample{The example shows how initializer lists are treated as
15897
    objects when possible.,push_back__initializer_list}
15898
    */
15899
    void push_back(initializer_list_t init)
15900
    {
15901
        if (is_object() and init.size() == 2 and (*init.begin())->is_string())
15902
        {
15903
            basic_json&& key = init.begin()->moved_or_copied();
15904
            push_back(typename object_t::value_type(
15905
                          std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
15906
        }
15907
        else
15908
        {
15909
            push_back(basic_json(init));
15910
        }
15911
    }
15912
15913
    /*!
15914
    @brief add an object to an object
15915
    @copydoc push_back(initializer_list_t)
15916
    */
15917
    reference operator+=(initializer_list_t init)
15918
    {
15919
        push_back(init);
15920
        return *this;
15921
    }
15922
15923
    /*!
15924
    @brief add an object to an array
15925
15926
    Creates a JSON value from the passed parameters @a args to the end of the
15927
    JSON value. If the function is called on a JSON null value, an empty array
15928
    is created before appending the value created from @a args.
15929
15930
    @param[in] args arguments to forward to a constructor of @ref basic_json
15931
    @tparam Args compatible types to create a @ref basic_json object
15932
15933
    @throw type_error.311 when called on a type other than JSON array or
15934
    null; example: `"cannot use emplace_back() with number"`
15935
15936
    @complexity Amortized constant.
15937
15938
    @liveexample{The example shows how `push_back()` can be used to add
15939
    elements to a JSON array. Note how the `null` value was silently converted
15940
    to a JSON array.,emplace_back}
15941
15942
    @since version 2.0.8
15943
    */
15944
    template<class... Args>
15945
    void emplace_back(Args&& ... args)
15946
    {
15947
        // emplace_back only works for null objects or arrays
15948
        if (JSON_UNLIKELY(not(is_null() or is_array())))
15949
        {
15950
            JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
15951
        }
15952
15953
        // transform null object into an array
15954
        if (is_null())
15955
        {
15956
            m_type = value_t::array;
15957
            m_value = value_t::array;
15958
            assert_invariant();
15959
        }
15960
15961
        // add element to array (perfect forwarding)
15962
        m_value.array->emplace_back(std::forward<Args>(args)...);
15963
    }
15964
15965
    /*!
15966
    @brief add an object to an object if key does not exist
15967
15968
    Inserts a new element into a JSON object constructed in-place with the
15969
    given @a args if there is no element with the key in the container. If the
15970
    function is called on a JSON null value, an empty object is created before
15971
    appending the value created from @a args.
15972
15973
    @param[in] args arguments to forward to a constructor of @ref basic_json
15974
    @tparam Args compatible types to create a @ref basic_json object
15975
15976
    @return a pair consisting of an iterator to the inserted element, or the
15977
            already-existing element if no insertion happened, and a bool
15978
            denoting whether the insertion took place.
15979
15980
    @throw type_error.311 when called on a type other than JSON object or
15981
    null; example: `"cannot use emplace() with number"`
15982
15983
    @complexity Logarithmic in the size of the container, O(log(`size()`)).
15984
15985
    @liveexample{The example shows how `emplace()` can be used to add elements
15986
    to a JSON object. Note how the `null` value was silently converted to a
15987
    JSON object. Further note how no value is added if there was already one
15988
    value stored with the same key.,emplace}
15989
15990
    @since version 2.0.8
15991
    */
15992
    template<class... Args>
15993
    std::pair<iterator, bool> emplace(Args&& ... args)
15994
    {
15995
        // emplace only works for null objects or arrays
15996
        if (JSON_UNLIKELY(not(is_null() or is_object())))
15997
        {
15998
            JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
15999
        }
16000
16001
        // transform null object into an object
16002
        if (is_null())
16003
        {
16004
            m_type = value_t::object;
16005
            m_value = value_t::object;
16006
            assert_invariant();
16007
        }
16008
16009
        // add element to array (perfect forwarding)
16010
        auto res = m_value.object->emplace(std::forward<Args>(args)...);
16011
        // create result iterator and set iterator to the result of emplace
16012
        auto it = begin();
16013
        it.m_it.object_iterator = res.first;
16014
16015
        // return pair of iterator and boolean
16016
        return {it, res.second};
16017
    }
16018
16019
    /*!
16020
    @brief inserts element
16021
16022
    Inserts element @a val before iterator @a pos.
16023
16024
    @param[in] pos iterator before which the content will be inserted; may be
16025
    the end() iterator
16026
    @param[in] val element to insert
16027
    @return iterator pointing to the inserted @a val.
16028
16029
    @throw type_error.309 if called on JSON values other than arrays;
16030
    example: `"cannot use insert() with string"`
16031
    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
16032
    example: `"iterator does not fit current value"`
16033
16034
    @complexity Constant plus linear in the distance between @a pos and end of
16035
    the container.
16036
16037
    @liveexample{The example shows how `insert()` is used.,insert}
16038
16039
    @since version 1.0.0
16040
    */
16041
    iterator insert(const_iterator pos, const basic_json& val)
16042
    {
16043
        // insert only works for arrays
16044
        if (JSON_LIKELY(is_array()))
16045
        {
16046
            // check if iterator pos fits to this JSON value
16047
            if (JSON_UNLIKELY(pos.m_object != this))
16048
            {
16049
                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
16050
            }
16051
16052
            // insert to array and return iterator
16053
            iterator result(this);
16054
            result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
16055
            return result;
16056
        }
16057
16058
        JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
16059
    }
16060
16061
    /*!
16062
    @brief inserts element
16063
    @copydoc insert(const_iterator, const basic_json&)
16064
    */
16065
    iterator insert(const_iterator pos, basic_json&& val)
16066
    {
16067
        return insert(pos, val);
16068
    }
16069
16070
    /*!
16071
    @brief inserts elements
16072
16073
    Inserts @a cnt copies of @a val before iterator @a pos.
16074
16075
    @param[in] pos iterator before which the content will be inserted; may be
16076
    the end() iterator
16077
    @param[in] cnt number of copies of @a val to insert
16078
    @param[in] val element to insert
16079
    @return iterator pointing to the first element inserted, or @a pos if
16080
    `cnt==0`
16081
16082
    @throw type_error.309 if called on JSON values other than arrays; example:
16083
    `"cannot use insert() with string"`
16084
    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
16085
    example: `"iterator does not fit current value"`
16086
16087
    @complexity Linear in @a cnt plus linear in the distance between @a pos
16088
    and end of the container.
16089
16090
    @liveexample{The example shows how `insert()` is used.,insert__count}
16091
16092
    @since version 1.0.0
16093
    */
16094
    iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
16095
    {
16096
        // insert only works for arrays
16097
        if (JSON_LIKELY(is_array()))
16098
        {
16099
            // check if iterator pos fits to this JSON value
16100
            if (JSON_UNLIKELY(pos.m_object != this))
16101
            {
16102
                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
16103
            }
16104
16105
            // insert to array and return iterator
16106
            iterator result(this);
16107
            result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
16108
            return result;
16109
        }
16110
16111
        JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
16112
    }
16113
16114
    /*!
16115
    @brief inserts elements
16116
16117
    Inserts elements from range `[first, last)` before iterator @a pos.
16118
16119
    @param[in] pos iterator before which the content will be inserted; may be
16120
    the end() iterator
16121
    @param[in] first begin of the range of elements to insert
16122
    @param[in] last end of the range of elements to insert
16123
16124
    @throw type_error.309 if called on JSON values other than arrays; example:
16125
    `"cannot use insert() with string"`
16126
    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
16127
    example: `"iterator does not fit current value"`
16128
    @throw invalid_iterator.210 if @a first and @a last do not belong to the
16129
    same JSON value; example: `"iterators do not fit"`
16130
    @throw invalid_iterator.211 if @a first or @a last are iterators into
16131
    container for which insert is called; example: `"passed iterators may not
16132
    belong to container"`
16133
16134
    @return iterator pointing to the first element inserted, or @a pos if
16135
    `first==last`
16136
16137
    @complexity Linear in `std::distance(first, last)` plus linear in the
16138
    distance between @a pos and end of the container.
16139
16140
    @liveexample{The example shows how `insert()` is used.,insert__range}
16141
16142
    @since version 1.0.0
16143
    */
16144
    iterator insert(const_iterator pos, const_iterator first, const_iterator last)
16145
    {
16146
        // insert only works for arrays
16147
        if (JSON_UNLIKELY(not is_array()))
16148
        {
16149
            JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
16150
        }
16151
16152
        // check if iterator pos fits to this JSON value
16153
        if (JSON_UNLIKELY(pos.m_object != this))
16154
        {
16155
            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
16156
        }
16157
16158
        // check if range iterators belong to the same JSON object
16159
        if (JSON_UNLIKELY(first.m_object != last.m_object))
16160
        {
16161
            JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
16162
        }
16163
16164
        if (JSON_UNLIKELY(first.m_object == this))
16165
        {
16166
            JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
16167
        }
16168
16169
        // insert to array and return iterator
16170
        iterator result(this);
16171
        result.m_it.array_iterator = m_value.array->insert(
16172
                                         pos.m_it.array_iterator,
16173
                                         first.m_it.array_iterator,
16174
                                         last.m_it.array_iterator);
16175
        return result;
16176
    }
16177
16178
    /*!
16179
    @brief inserts elements
16180
16181
    Inserts elements from initializer list @a ilist before iterator @a pos.
16182
16183
    @param[in] pos iterator before which the content will be inserted; may be
16184
    the end() iterator
16185
    @param[in] ilist initializer list to insert the values from
16186
16187
    @throw type_error.309 if called on JSON values other than arrays; example:
16188
    `"cannot use insert() with string"`
16189
    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
16190
    example: `"iterator does not fit current value"`
16191
16192
    @return iterator pointing to the first element inserted, or @a pos if
16193
    `ilist` is empty
16194
16195
    @complexity Linear in `ilist.size()` plus linear in the distance between
16196
    @a pos and end of the container.
16197
16198
    @liveexample{The example shows how `insert()` is used.,insert__ilist}
16199
16200
    @since version 1.0.0
16201
    */
16202
    iterator insert(const_iterator pos, initializer_list_t ilist)
16203
    {
16204
        // insert only works for arrays
16205
        if (JSON_UNLIKELY(not is_array()))
16206
        {
16207
            JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
16208
        }
16209
16210
        // check if iterator pos fits to this JSON value
16211
        if (JSON_UNLIKELY(pos.m_object != this))
16212
        {
16213
            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
16214
        }
16215
16216
        // insert to array and return iterator
16217
        iterator result(this);
16218
        result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist.begin(), ilist.end());
16219
        return result;
16220
    }
16221
16222
    /*!
16223
    @brief inserts elements
16224
16225
    Inserts elements from range `[first, last)`.
16226
16227
    @param[in] first begin of the range of elements to insert
16228
    @param[in] last end of the range of elements to insert
16229
16230
    @throw type_error.309 if called on JSON values other than objects; example:
16231
    `"cannot use insert() with string"`
16232
    @throw invalid_iterator.202 if iterator @a first or @a last does does not
16233
    point to an object; example: `"iterators first and last must point to
16234
    objects"`
16235
    @throw invalid_iterator.210 if @a first and @a last do not belong to the
16236
    same JSON value; example: `"iterators do not fit"`
16237
16238
    @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number
16239
    of elements to insert.
16240
16241
    @liveexample{The example shows how `insert()` is used.,insert__range_object}
16242
16243
    @since version 3.0.0
16244
    */
16245
    void insert(const_iterator first, const_iterator last)
16246
    {
16247
        // insert only works for objects
16248
        if (JSON_UNLIKELY(not is_object()))
16249
        {
16250
            JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
16251
        }
16252
16253
        // check if range iterators belong to the same JSON object
16254
        if (JSON_UNLIKELY(first.m_object != last.m_object))
16255
        {
16256
            JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
16257
        }
16258
16259
        // passed iterators must belong to objects
16260
        if (JSON_UNLIKELY(not first.m_object->is_object()))
16261
        {
16262
            JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
16263
        }
16264
16265
        m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
16266
    }
16267
16268
    /*!
16269
    @brief updates a JSON object from another object, overwriting existing keys
16270
16271
    Inserts all values from JSON object @a j and overwrites existing keys.
16272
16273
    @param[in] j  JSON object to read values from
16274
16275
    @throw type_error.312 if called on JSON values other than objects; example:
16276
    `"cannot use update() with string"`
16277
16278
    @complexity O(N*log(size() + N)), where N is the number of elements to
16279
                insert.
16280
16281
    @liveexample{The example shows how `update()` is used.,update}
16282
16283
    @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
16284
16285
    @since version 3.0.0
16286
    */
16287
    void update(const_reference j)
16288
    {
16289
        // implicitly convert null value to an empty object
16290
        if (is_null())
16291
        {
16292
            m_type = value_t::object;
16293
            m_value.object = create<object_t>();
16294
            assert_invariant();
16295
        }
16296
16297
        if (JSON_UNLIKELY(not is_object()))
16298
        {
16299
            JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
16300
        }
16301
        if (JSON_UNLIKELY(not j.is_object()))
16302
        {
16303
            JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
16304
        }
16305
16306
        for (auto it = j.cbegin(); it != j.cend(); ++it)
16307
        {
16308
            m_value.object->operator[](it.key()) = it.value();
16309
        }
16310
    }
16311
16312
    /*!
16313
    @brief updates a JSON object from another object, overwriting existing keys
16314
16315
    Inserts all values from from range `[first, last)` and overwrites existing
16316
    keys.
16317
16318
    @param[in] first begin of the range of elements to insert
16319
    @param[in] last end of the range of elements to insert
16320
16321
    @throw type_error.312 if called on JSON values other than objects; example:
16322
    `"cannot use update() with string"`
16323
    @throw invalid_iterator.202 if iterator @a first or @a last does does not
16324
    point to an object; example: `"iterators first and last must point to
16325
    objects"`
16326
    @throw invalid_iterator.210 if @a first and @a last do not belong to the
16327
    same JSON value; example: `"iterators do not fit"`
16328
16329
    @complexity O(N*log(size() + N)), where N is the number of elements to
16330
                insert.
16331
16332
    @liveexample{The example shows how `update()` is used__range.,update}
16333
16334
    @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
16335
16336
    @since version 3.0.0
16337
    */
16338
    void update(const_iterator first, const_iterator last)
16339
    {
16340
        // implicitly convert null value to an empty object
16341
        if (is_null())
16342
        {
16343
            m_type = value_t::object;
16344
            m_value.object = create<object_t>();
16345
            assert_invariant();
16346
        }
16347
16348
        if (JSON_UNLIKELY(not is_object()))
16349
        {
16350
            JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
16351
        }
16352
16353
        // check if range iterators belong to the same JSON object
16354
        if (JSON_UNLIKELY(first.m_object != last.m_object))
16355
        {
16356
            JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
16357
        }
16358
16359
        // passed iterators must belong to objects
16360
        if (JSON_UNLIKELY(not first.m_object->is_object()
16361
                          or not last.m_object->is_object()))
16362
        {
16363
            JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
16364
        }
16365
16366
        for (auto it = first; it != last; ++it)
16367
        {
16368
            m_value.object->operator[](it.key()) = it.value();
16369
        }
16370
    }
16371
16372
    /*!
16373
    @brief exchanges the values
16374
16375
    Exchanges the contents of the JSON value with those of @a other. Does not
16376
    invoke any move, copy, or swap operations on individual elements. All
16377
    iterators and references remain valid. The past-the-end iterator is
16378
    invalidated.
16379
16380
    @param[in,out] other JSON value to exchange the contents with
16381
16382
    @complexity Constant.
16383
16384
    @liveexample{The example below shows how JSON values can be swapped with
16385
    `swap()`.,swap__reference}
16386
16387
    @since version 1.0.0
16388
    */
16389
    void swap(reference other) noexcept (
16390
        std::is_nothrow_move_constructible<value_t>::value and
16391
        std::is_nothrow_move_assignable<value_t>::value and
16392
        std::is_nothrow_move_constructible<json_value>::value and
16393
        std::is_nothrow_move_assignable<json_value>::value
16394
    )
0
16395
    {
0
16396
        std::swap(m_type, other.m_type);
0
16397
        std::swap(m_value, other.m_value);
0
16398
        assert_invariant();
0
16399
    }
16400
16401
    /*!
16402
    @brief exchanges the values
16403
16404
    Exchanges the contents of a JSON array with those of @a other. Does not
16405
    invoke any move, copy, or swap operations on individual elements. All
16406
    iterators and references remain valid. The past-the-end iterator is
16407
    invalidated.
16408
16409
    @param[in,out] other array to exchange the contents with
16410
16411
    @throw type_error.310 when JSON value is not an array; example: `"cannot
16412
    use swap() with string"`
16413
16414
    @complexity Constant.
16415
16416
    @liveexample{The example below shows how arrays can be swapped with
16417
    `swap()`.,swap__array_t}
16418
16419
    @since version 1.0.0
16420
    */
16421
    void swap(array_t& other)
16422
    {
16423
        // swap only works for arrays
16424
        if (JSON_LIKELY(is_array()))
16425
        {
16426
            std::swap(*(m_value.array), other);
16427
        }
16428
        else
16429
        {
16430
            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
16431
        }
16432
    }
16433
16434
    /*!
16435
    @brief exchanges the values
16436
16437
    Exchanges the contents of a JSON object with those of @a other. Does not
16438
    invoke any move, copy, or swap operations on individual elements. All
16439
    iterators and references remain valid. The past-the-end iterator is
16440
    invalidated.
16441
16442
    @param[in,out] other object to exchange the contents with
16443
16444
    @throw type_error.310 when JSON value is not an object; example:
16445
    `"cannot use swap() with string"`
16446
16447
    @complexity Constant.
16448
16449
    @liveexample{The example below shows how objects can be swapped with
16450
    `swap()`.,swap__object_t}
16451
16452
    @since version 1.0.0
16453
    */
16454
    void swap(object_t& other)
16455
    {
16456
        // swap only works for objects
16457
        if (JSON_LIKELY(is_object()))
16458
        {
16459
            std::swap(*(m_value.object), other);
16460
        }
16461
        else
16462
        {
16463
            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
16464
        }
16465
    }
16466
16467
    /*!
16468
    @brief exchanges the values
16469
16470
    Exchanges the contents of a JSON string with those of @a other. Does not
16471
    invoke any move, copy, or swap operations on individual elements. All
16472
    iterators and references remain valid. The past-the-end iterator is
16473
    invalidated.
16474
16475
    @param[in,out] other string to exchange the contents with
16476
16477
    @throw type_error.310 when JSON value is not a string; example: `"cannot
16478
    use swap() with boolean"`
16479
16480
    @complexity Constant.
16481
16482
    @liveexample{The example below shows how strings can be swapped with
16483
    `swap()`.,swap__string_t}
16484
16485
    @since version 1.0.0
16486
    */
16487
    void swap(string_t& other)
16488
    {
16489
        // swap only works for strings
16490
        if (JSON_LIKELY(is_string()))
16491
        {
16492
            std::swap(*(m_value.string), other);
16493
        }
16494
        else
16495
        {
16496
            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
16497
        }
16498
    }
16499
16500
    /// @}
16501
16502
  public:
16503
    //////////////////////////////////////////
16504
    // lexicographical comparison operators //
16505
    //////////////////////////////////////////
16506
16507
    /// @name lexicographical comparison operators
16508
    /// @{
16509
16510
    /*!
16511
    @brief comparison: equal
16512
16513
    Compares two JSON values for equality according to the following rules:
16514
    - Two JSON values are equal if (1) they are from the same type and (2)
16515
      their stored values are the same according to their respective
16516
      `operator==`.
16517
    - Integer and floating-point numbers are automatically converted before
16518
      comparison. Note than two NaN values are always treated as unequal.
16519
    - Two JSON null values are equal.
16520
16521
    @note Floating-point inside JSON values numbers are compared with
16522
    `json::number_float_t::operator==` which is `double::operator==` by
16523
    default. To compare floating-point while respecting an epsilon, an alternative
16524
    [comparison function](https://github.com/mariokonrad/marnav/blob/master/src/marnav/math/floatingpoint.hpp#L34-#L39)
16525
    could be used, for instance
16526
    @code {.cpp}
16527
    template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
16528
    inline bool is_same(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) noexcept
16529
    {
16530
        return std::abs(a - b) <= epsilon;
16531
    }
16532
    @endcode
16533
16534
    @note NaN values never compare equal to themselves or to other NaN values.
16535
16536
    @param[in] lhs  first JSON value to consider
16537
    @param[in] rhs  second JSON value to consider
16538
    @return whether the values @a lhs and @a rhs are equal
16539
16540
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16541
16542
    @complexity Linear.
16543
16544
    @liveexample{The example demonstrates comparing several JSON
16545
    types.,operator__equal}
16546
16547
    @since version 1.0.0
16548
    */
16549
    friend bool operator==(const_reference lhs, const_reference rhs) noexcept
40
16550
    {
40
16551
        const auto lhs_type = lhs.type();
40
16552
        const auto rhs_type = rhs.type();
40
16553
40
16554
        if (lhs_type == rhs_type)
40
16555
        {
0
16556
            switch (lhs_type)
0
16557
            {
0
16558
                case value_t::array:
0
16559
                    return (*lhs.m_value.array == *rhs.m_value.array);
0
16560
0
16561
                case value_t::object:
0
16562
                    return (*lhs.m_value.object == *rhs.m_value.object);
0
16563
0
16564
                case value_t::null:
0
16565
                    return true;
0
16566
40
16567
                case value_t::string:
40
16568
                    return (*lhs.m_value.string == *rhs.m_value.string);
0
16569
0
16570
                case value_t::boolean:
0
16571
                    return (lhs.m_value.boolean == rhs.m_value.boolean);
0
16572
0
16573
                case value_t::number_integer:
0
16574
                    return (lhs.m_value.number_integer == rhs.m_value.number_integer);
0
16575
0
16576
                case value_t::number_unsigned:
0
16577
                    return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned);
0
16578
0
16579
                case value_t::number_float:
0
16580
                    return (lhs.m_value.number_float == rhs.m_value.number_float);
0
16581
0
16582
                default:
0
16583
                    return false;
0
16584
            }
40
16585
        }
0
16586
        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
0
16587
        {
0
16588
            return (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float);
0
16589
        }
0
16590
        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
0
16591
        {
0
16592
            return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer));
0
16593
        }
0
16594
        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
0
16595
        {
0
16596
            return (static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float);
0
16597
        }
0
16598
        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
0
16599
        {
0
16600
            return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned));
0
16601
        }
0
16602
        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
0
16603
        {
0
16604
            return (static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer);
0
16605
        }
0
16606
        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
0
16607
        {
0
16608
            return (lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned));
0
16609
        }
40
16610
0
16611
        return false;
40
16612
    }
16613
16614
    /*!
16615
    @brief comparison: equal
16616
    @copydoc operator==(const_reference, const_reference)
16617
    */
16618
    template<typename ScalarType, typename std::enable_if<
16619
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16620
    friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
40
16621
    {
40
16622
        return (lhs == basic_json(rhs));
40
16623
    }
16624
16625
    /*!
16626
    @brief comparison: equal
16627
    @copydoc operator==(const_reference, const_reference)
16628
    */
16629
    template<typename ScalarType, typename std::enable_if<
16630
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16631
    friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
16632
    {
16633
        return (basic_json(lhs) == rhs);
16634
    }
16635
16636
    /*!
16637
    @brief comparison: not equal
16638
16639
    Compares two JSON values for inequality by calculating `not (lhs == rhs)`.
16640
16641
    @param[in] lhs  first JSON value to consider
16642
    @param[in] rhs  second JSON value to consider
16643
    @return whether the values @a lhs and @a rhs are not equal
16644
16645
    @complexity Linear.
16646
16647
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16648
16649
    @liveexample{The example demonstrates comparing several JSON
16650
    types.,operator__notequal}
16651
16652
    @since version 1.0.0
16653
    */
16654
    friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
16655
    {
16656
        return not (lhs == rhs);
16657
    }
16658
16659
    /*!
16660
    @brief comparison: not equal
16661
    @copydoc operator!=(const_reference, const_reference)
16662
    */
16663
    template<typename ScalarType, typename std::enable_if<
16664
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16665
    friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
16666
    {
16667
        return (lhs != basic_json(rhs));
16668
    }
16669
16670
    /*!
16671
    @brief comparison: not equal
16672
    @copydoc operator!=(const_reference, const_reference)
16673
    */
16674
    template<typename ScalarType, typename std::enable_if<
16675
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16676
    friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
16677
    {
16678
        return (basic_json(lhs) != rhs);
16679
    }
16680
16681
    /*!
16682
    @brief comparison: less than
16683
16684
    Compares whether one JSON value @a lhs is less than another JSON value @a
16685
    rhs according to the following rules:
16686
    - If @a lhs and @a rhs have the same type, the values are compared using
16687
      the default `<` operator.
16688
    - Integer and floating-point numbers are automatically converted before
16689
      comparison
16690
    - In case @a lhs and @a rhs have different types, the values are ignored
16691
      and the order of the types is considered, see
16692
      @ref operator<(const value_t, const value_t).
16693
16694
    @param[in] lhs  first JSON value to consider
16695
    @param[in] rhs  second JSON value to consider
16696
    @return whether @a lhs is less than @a rhs
16697
16698
    @complexity Linear.
16699
16700
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16701
16702
    @liveexample{The example demonstrates comparing several JSON
16703
    types.,operator__less}
16704
16705
    @since version 1.0.0
16706
    */
16707
    friend bool operator<(const_reference lhs, const_reference rhs) noexcept
16708
    {
16709
        const auto lhs_type = lhs.type();
16710
        const auto rhs_type = rhs.type();
16711
16712
        if (lhs_type == rhs_type)
16713
        {
16714
            switch (lhs_type)
16715
            {
16716
                case value_t::array:
16717
                    return (*lhs.m_value.array) < (*rhs.m_value.array);
16718
16719
                case value_t::object:
16720
                    return *lhs.m_value.object < *rhs.m_value.object;
16721
16722
                case value_t::null:
16723
                    return false;
16724
16725
                case value_t::string:
16726
                    return *lhs.m_value.string < *rhs.m_value.string;
16727
16728
                case value_t::boolean:
16729
                    return lhs.m_value.boolean < rhs.m_value.boolean;
16730
16731
                case value_t::number_integer:
16732
                    return lhs.m_value.number_integer < rhs.m_value.number_integer;
16733
16734
                case value_t::number_unsigned:
16735
                    return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
16736
16737
                case value_t::number_float:
16738
                    return lhs.m_value.number_float < rhs.m_value.number_float;
16739
16740
                default:
16741
                    return false;
16742
            }
16743
        }
16744
        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
16745
        {
16746
            return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
16747
        }
16748
        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
16749
        {
16750
            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
16751
        }
16752
        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
16753
        {
16754
            return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
16755
        }
16756
        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
16757
        {
16758
            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
16759
        }
16760
        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
16761
        {
16762
            return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
16763
        }
16764
        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
16765
        {
16766
            return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
16767
        }
16768
16769
        // We only reach this line if we cannot compare values. In that case,
16770
        // we compare types. Note we have to call the operator explicitly,
16771
        // because MSVC has problems otherwise.
16772
        return operator<(lhs_type, rhs_type);
16773
    }
16774
16775
    /*!
16776
    @brief comparison: less than
16777
    @copydoc operator<(const_reference, const_reference)
16778
    */
16779
    template<typename ScalarType, typename std::enable_if<
16780
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16781
    friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
16782
    {
16783
        return (lhs < basic_json(rhs));
16784
    }
16785
16786
    /*!
16787
    @brief comparison: less than
16788
    @copydoc operator<(const_reference, const_reference)
16789
    */
16790
    template<typename ScalarType, typename std::enable_if<
16791
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16792
    friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
16793
    {
16794
        return (basic_json(lhs) < rhs);
16795
    }
16796
16797
    /*!
16798
    @brief comparison: less than or equal
16799
16800
    Compares whether one JSON value @a lhs is less than or equal to another
16801
    JSON value by calculating `not (rhs < lhs)`.
16802
16803
    @param[in] lhs  first JSON value to consider
16804
    @param[in] rhs  second JSON value to consider
16805
    @return whether @a lhs is less than or equal to @a rhs
16806
16807
    @complexity Linear.
16808
16809
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16810
16811
    @liveexample{The example demonstrates comparing several JSON
16812
    types.,operator__greater}
16813
16814
    @since version 1.0.0
16815
    */
16816
    friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
16817
    {
16818
        return not (rhs < lhs);
16819
    }
16820
16821
    /*!
16822
    @brief comparison: less than or equal
16823
    @copydoc operator<=(const_reference, const_reference)
16824
    */
16825
    template<typename ScalarType, typename std::enable_if<
16826
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16827
    friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
16828
    {
16829
        return (lhs <= basic_json(rhs));
16830
    }
16831
16832
    /*!
16833
    @brief comparison: less than or equal
16834
    @copydoc operator<=(const_reference, const_reference)
16835
    */
16836
    template<typename ScalarType, typename std::enable_if<
16837
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16838
    friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
16839
    {
16840
        return (basic_json(lhs) <= rhs);
16841
    }
16842
16843
    /*!
16844
    @brief comparison: greater than
16845
16846
    Compares whether one JSON value @a lhs is greater than another
16847
    JSON value by calculating `not (lhs <= rhs)`.
16848
16849
    @param[in] lhs  first JSON value to consider
16850
    @param[in] rhs  second JSON value to consider
16851
    @return whether @a lhs is greater than to @a rhs
16852
16853
    @complexity Linear.
16854
16855
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16856
16857
    @liveexample{The example demonstrates comparing several JSON
16858
    types.,operator__lessequal}
16859
16860
    @since version 1.0.0
16861
    */
16862
    friend bool operator>(const_reference lhs, const_reference rhs) noexcept
16863
    {
16864
        return not (lhs <= rhs);
16865
    }
16866
16867
    /*!
16868
    @brief comparison: greater than
16869
    @copydoc operator>(const_reference, const_reference)
16870
    */
16871
    template<typename ScalarType, typename std::enable_if<
16872
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16873
    friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
16874
    {
16875
        return (lhs > basic_json(rhs));
16876
    }
16877
16878
    /*!
16879
    @brief comparison: greater than
16880
    @copydoc operator>(const_reference, const_reference)
16881
    */
16882
    template<typename ScalarType, typename std::enable_if<
16883
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16884
    friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
16885
    {
16886
        return (basic_json(lhs) > rhs);
16887
    }
16888
16889
    /*!
16890
    @brief comparison: greater than or equal
16891
16892
    Compares whether one JSON value @a lhs is greater than or equal to another
16893
    JSON value by calculating `not (lhs < rhs)`.
16894
16895
    @param[in] lhs  first JSON value to consider
16896
    @param[in] rhs  second JSON value to consider
16897
    @return whether @a lhs is greater than or equal to @a rhs
16898
16899
    @complexity Linear.
16900
16901
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16902
16903
    @liveexample{The example demonstrates comparing several JSON
16904
    types.,operator__greaterequal}
16905
16906
    @since version 1.0.0
16907
    */
16908
    friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
16909
    {
16910
        return not (lhs < rhs);
16911
    }
16912
16913
    /*!
16914
    @brief comparison: greater than or equal
16915
    @copydoc operator>=(const_reference, const_reference)
16916
    */
16917
    template<typename ScalarType, typename std::enable_if<
16918
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16919
    friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
16920
    {
16921
        return (lhs >= basic_json(rhs));
16922
    }
16923
16924
    /*!
16925
    @brief comparison: greater than or equal
16926
    @copydoc operator>=(const_reference, const_reference)
16927
    */
16928
    template<typename ScalarType, typename std::enable_if<
16929
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16930
    friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
16931
    {
16932
        return (basic_json(lhs) >= rhs);
16933
    }
16934
16935
    /// @}
16936
16937
    ///////////////////
16938
    // serialization //
16939
    ///////////////////
16940
16941
    /// @name serialization
16942
    /// @{
16943
16944
    /*!
16945
    @brief serialize to stream
16946
16947
    Serialize the given JSON value @a j to the output stream @a o. The JSON
16948
    value will be serialized using the @ref dump member function.
16949
16950
    - The indentation of the output can be controlled with the member variable
16951
      `width` of the output stream @a o. For instance, using the manipulator
16952
      `std::setw(4)` on @a o sets the indentation level to `4` and the
16953
      serialization result is the same as calling `dump(4)`.
16954
16955
    - The indentation character can be controlled with the member variable
16956
      `fill` of the output stream @a o. For instance, the manipulator
16957
      `std::setfill('\\t')` sets indentation to use a tab character rather than
16958
      the default space character.
16959
16960
    @param[in,out] o  stream to serialize to
16961
    @param[in] j  JSON value to serialize
16962
16963
    @return the stream @a o
16964
16965
    @throw type_error.316 if a string stored inside the JSON value is not
16966
                          UTF-8 encoded
16967
16968
    @complexity Linear.
16969
16970
    @liveexample{The example below shows the serialization with different
16971
    parameters to `width` to adjust the indentation level.,operator_serialize}
16972
16973
    @since version 1.0.0; indentation character added in version 3.0.0
16974
    */
16975
    friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
372
16976
    {
372
16977
        // read width member and use it as indentation parameter if nonzero
372
16978
        const bool pretty_print = (o.width() > 0);
208
16979
        const auto indentation = (pretty_print ? o.width() : 0);
372
16980
372
16981
        // reset width to 0 for subsequent calls to this stream
372
16982
        o.width(0);
372
16983
372
16984
        // do the actual serialization
372
16985
        serializer s(detail::output_adapter<char>(o), o.fill());
372
16986
        s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
372
16987
        return o;
372
16988
    }
16989
16990
    /*!
16991
    @brief serialize to stream
16992
    @deprecated This stream operator is deprecated and will be removed in
16993
                future 4.0.0 of the library. Please use
16994
                @ref operator<<(std::ostream&, const basic_json&)
16995
                instead; that is, replace calls like `j >> o;` with `o << j;`.
16996
    @since version 1.0.0; deprecated since version 3.0.0
16997
    */
16998
    JSON_DEPRECATED
16999
    friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
17000
    {
17001
        return o << j;
17002
    }
17003
17004
    /// @}
17005
17006
17007
    /////////////////////
17008
    // deserialization //
17009
    /////////////////////
17010
17011
    /// @name deserialization
17012
    /// @{
17013
17014
    /*!
17015
    @brief deserialize from a compatible input
17016
17017
    This function reads from a compatible input. Examples are:
17018
    - an array of 1-byte values
17019
    - strings with character/literal type with size of 1 byte
17020
    - input streams
17021
    - container with contiguous storage of 1-byte values. Compatible container
17022
      types include `std::vector`, `std::string`, `std::array`,
17023
      `std::valarray`, and `std::initializer_list`. Furthermore, C-style
17024
      arrays can be used with `std::begin()`/`std::end()`. User-defined
17025
      containers can be used as long as they implement random-access iterators
17026
      and a contiguous storage.
17027
17028
    @pre Each element of the container has a size of 1 byte. Violating this
17029
    precondition yields undefined behavior. **This precondition is enforced
17030
    with a static assertion.**
17031
17032
    @pre The container storage is contiguous. Violating this precondition
17033
    yields undefined behavior. **This precondition is enforced with an
17034
    assertion.**
17035
    @pre Each element of the container has a size of 1 byte. Violating this
17036
    precondition yields undefined behavior. **This precondition is enforced
17037
    with a static assertion.**
17038
17039
    @warning There is no way to enforce all preconditions at compile-time. If
17040
             the function is called with a noncompliant container and with
17041
             assertions switched off, the behavior is undefined and will most
17042
             likely yield segmentation violation.
17043
17044
    @param[in] i  input to read from
17045
    @param[in] cb  a parser callback function of type @ref parser_callback_t
17046
    which is used to control the deserialization by filtering unwanted values
17047
    (optional)
17048
17049
    @return result of the deserialization
17050
17051
    @throw parse_error.101 if a parse error occurs; example: `""unexpected end
17052
    of input; expected string literal""`
17053
    @throw parse_error.102 if to_unicode fails or surrogate error
17054
    @throw parse_error.103 if to_unicode fails
17055
17056
    @complexity Linear in the length of the input. The parser is a predictive
17057
    LL(1) parser. The complexity can be higher if the parser callback function
17058
    @a cb has a super-linear complexity.
17059
17060
    @note A UTF-8 byte order mark is silently ignored.
17061
17062
    @liveexample{The example below demonstrates the `parse()` function reading
17063
    from an array.,parse__array__parser_callback_t}
17064
17065
    @liveexample{The example below demonstrates the `parse()` function with
17066
    and without callback function.,parse__string__parser_callback_t}
17067
17068
    @liveexample{The example below demonstrates the `parse()` function with
17069
    and without callback function.,parse__istream__parser_callback_t}
17070
17071
    @liveexample{The example below demonstrates the `parse()` function reading
17072
    from a contiguous container.,parse__contiguouscontainer__parser_callback_t}
17073
17074
    @since version 2.0.3 (contiguous containers)
17075
    */
17076
    static basic_json parse(detail::input_adapter&& i,
17077
                            const parser_callback_t cb = nullptr,
17078
                            const bool allow_exceptions = true)
1.80k
17079
    {
1.80k
17080
        basic_json result;
1.80k
17081
        parser(i, cb, allow_exceptions).parse(true, result);
1.80k
17082
        return result;
1.80k
17083
    }
17084
17085
    static bool accept(detail::input_adapter&& i)
17086
    {
17087
        return parser(i).accept(true);
17088
    }
17089
17090
    /*!
17091
    @brief generate SAX events
17092
17093
    The SAX event lister must follow the interface of @ref json_sax.
17094
17095
    This function reads from a compatible input. Examples are:
17096
    - an array of 1-byte values
17097
    - strings with character/literal type with size of 1 byte
17098
    - input streams
17099
    - container with contiguous storage of 1-byte values. Compatible container
17100
      types include `std::vector`, `std::string`, `std::array`,
17101
      `std::valarray`, and `std::initializer_list`. Furthermore, C-style
17102
      arrays can be used with `std::begin()`/`std::end()`. User-defined
17103
      containers can be used as long as they implement random-access iterators
17104
      and a contiguous storage.
17105
17106
    @pre Each element of the container has a size of 1 byte. Violating this
17107
    precondition yields undefined behavior. **This precondition is enforced
17108
    with a static assertion.**
17109
17110
    @pre The container storage is contiguous. Violating this precondition
17111
    yields undefined behavior. **This precondition is enforced with an
17112
    assertion.**
17113
    @pre Each element of the container has a size of 1 byte. Violating this
17114
    precondition yields undefined behavior. **This precondition is enforced
17115
    with a static assertion.**
17116
17117
    @warning There is no way to enforce all preconditions at compile-time. If
17118
             the function is called with a noncompliant container and with
17119
             assertions switched off, the behavior is undefined and will most
17120
             likely yield segmentation violation.
17121
17122
    @param[in] i  input to read from
17123
    @param[in,out] sax  SAX event listener
17124
    @param[in] format  the format to parse (JSON, CBOR, MessagePack, or UBJSON)
17125
    @param[in] strict  whether the input has to be consumed completely
17126
17127
    @return return value of the last processed SAX event
17128
17129
    @throw parse_error.101 if a parse error occurs; example: `""unexpected end
17130
    of input; expected string literal""`
17131
    @throw parse_error.102 if to_unicode fails or surrogate error
17132
    @throw parse_error.103 if to_unicode fails
17133
17134
    @complexity Linear in the length of the input. The parser is a predictive
17135
    LL(1) parser. The complexity can be higher if the SAX consumer @a sax has
17136
    a super-linear complexity.
17137
17138
    @note A UTF-8 byte order mark is silently ignored.
17139
17140
    @liveexample{The example below demonstrates the `sax_parse()` function
17141
    reading from string and processing the events with a user-defined SAX
17142
    event consumer.,sax_parse}
17143
17144
    @since version 3.2.0
17145
    */
17146
    template <typename SAX>
17147
    static bool sax_parse(detail::input_adapter&& i, SAX* sax,
17148
                          input_format_t format = input_format_t::json,
17149
                          const bool strict = true)
17150
    {
17151
        assert(sax);
17152
        switch (format)
17153
        {
17154
            case input_format_t::json:
17155
                return parser(std::move(i)).sax_parse(sax, strict);
17156
            default:
17157
                return detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
17158
        }
17159
    }
17160
17161
    /*!
17162
    @brief deserialize from an iterator range with contiguous storage
17163
17164
    This function reads from an iterator range of a container with contiguous
17165
    storage of 1-byte values. Compatible container types include
17166
    `std::vector`, `std::string`, `std::array`, `std::valarray`, and
17167
    `std::initializer_list`. Furthermore, C-style arrays can be used with
17168
    `std::begin()`/`std::end()`. User-defined containers can be used as long
17169
    as they implement random-access iterators and a contiguous storage.
17170
17171
    @pre The iterator range is contiguous. Violating this precondition yields
17172
    undefined behavior. **This precondition is enforced with an assertion.**
17173
    @pre Each element in the range has a size of 1 byte. Violating this
17174
    precondition yields undefined behavior. **This precondition is enforced
17175
    with a static assertion.**
17176
17177
    @warning There is no way to enforce all preconditions at compile-time. If
17178
             the function is called with noncompliant iterators and with
17179
             assertions switched off, the behavior is undefined and will most
17180
             likely yield segmentation violation.
17181
17182
    @tparam IteratorType iterator of container with contiguous storage
17183
    @param[in] first  begin of the range to parse (included)
17184
    @param[in] last  end of the range to parse (excluded)
17185
    @param[in] cb  a parser callback function of type @ref parser_callback_t
17186
    which is used to control the deserialization by filtering unwanted values
17187
    (optional)
17188
    @param[in] allow_exceptions  whether to throw exceptions in case of a
17189
    parse error (optional, true by default)
17190
17191
    @return result of the deserialization
17192
17193
    @throw parse_error.101 in case of an unexpected token
17194
    @throw parse_error.102 if to_unicode fails or surrogate error
17195
    @throw parse_error.103 if to_unicode fails
17196
17197
    @complexity Linear in the length of the input. The parser is a predictive
17198
    LL(1) parser. The complexity can be higher if the parser callback function
17199
    @a cb has a super-linear complexity.
17200
17201
    @note A UTF-8 byte order mark is silently ignored.
17202
17203
    @liveexample{The example below demonstrates the `parse()` function reading
17204
    from an iterator range.,parse__iteratortype__parser_callback_t}
17205
17206
    @since version 2.0.3
17207
    */
17208
    template<class IteratorType, typename std::enable_if<
17209
                 std::is_base_of<
17210
                     std::random_access_iterator_tag,
17211
                     typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
17212
    static basic_json parse(IteratorType first, IteratorType last,
17213
                            const parser_callback_t cb = nullptr,
17214
                            const bool allow_exceptions = true)
0
17215
    {
0
17216
        basic_json result;
0
17217
        parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);
0
17218
        return result;
0
17219
    }
17220
17221
    template<class IteratorType, typename std::enable_if<
17222
                 std::is_base_of<
17223
                     std::random_access_iterator_tag,
17224
                     typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
17225
    static bool accept(IteratorType first, IteratorType last)
17226
    {
17227
        return parser(detail::input_adapter(first, last)).accept(true);
17228
    }
17229
17230
    template<class IteratorType, class SAX, typename std::enable_if<
17231
                 std::is_base_of<
17232
                     std::random_access_iterator_tag,
17233
                     typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
17234
    static bool sax_parse(IteratorType first, IteratorType last, SAX* sax)
17235
    {
17236
        return parser(detail::input_adapter(first, last)).sax_parse(sax);
17237
    }
17238
17239
    /*!
17240
    @brief deserialize from stream
17241
    @deprecated This stream operator is deprecated and will be removed in
17242
                version 4.0.0 of the library. Please use
17243
                @ref operator>>(std::istream&, basic_json&)
17244
                instead; that is, replace calls like `j << i;` with `i >> j;`.
17245
    @since version 1.0.0; deprecated since version 3.0.0
17246
    */
17247
    JSON_DEPRECATED
17248
    friend std::istream& operator<<(basic_json& j, std::istream& i)
17249
    {
17250
        return operator>>(i, j);
17251
    }
17252
17253
    /*!
17254
    @brief deserialize from stream
17255
17256
    Deserializes an input stream to a JSON value.
17257
17258
    @param[in,out] i  input stream to read a serialized JSON value from
17259
    @param[in,out] j  JSON value to write the deserialized input to
17260
17261
    @throw parse_error.101 in case of an unexpected token
17262
    @throw parse_error.102 if to_unicode fails or surrogate error
17263
    @throw parse_error.103 if to_unicode fails
17264
17265
    @complexity Linear in the length of the input. The parser is a predictive
17266
    LL(1) parser.
17267
17268
    @note A UTF-8 byte order mark is silently ignored.
17269
17270
    @liveexample{The example below shows how a JSON value is constructed by
17271
    reading a serialization from a stream.,operator_deserialize}
17272
17273
    @sa parse(std::istream&, const parser_callback_t) for a variant with a
17274
    parser callback function to filter values while parsing
17275
17276
    @since version 1.0.0
17277
    */
17278
    friend std::istream& operator>>(std::istream& i, basic_json& j)
540
17279
    {
540
17280
        parser(detail::input_adapter(i)).parse(false, j);
540
17281
        return i;
540
17282
    }
17283
17284
    /// @}
17285
17286
    ///////////////////////////
17287
    // convenience functions //
17288
    ///////////////////////////
17289
17290
    /*!
17291
    @brief return the type as string
17292
17293
    Returns the type name as string to be used in error messages - usually to
17294
    indicate that a function was called on a wrong JSON type.
17295
17296
    @return a string representation of a the @a m_type member:
17297
            Value type  | return value
17298
            ----------- | -------------
17299
            null        | `"null"`
17300
            boolean     | `"boolean"`
17301
            string      | `"string"`
17302
            number      | `"number"` (for all number types)
17303
            object      | `"object"`
17304
            array       | `"array"`
17305
            discarded   | `"discarded"`
17306
17307
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
17308
17309
    @complexity Constant.
17310
17311
    @liveexample{The following code exemplifies `type_name()` for all JSON
17312
    types.,type_name}
17313
17314
    @sa @ref type() -- return the type of the JSON value
17315
    @sa @ref operator value_t() -- return the type of the JSON value (implicit)
17316
17317
    @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept`
17318
    since 3.0.0
17319
    */
17320
    const char* type_name() const noexcept
0
17321
    {
0
17322
        {
0
17323
            switch (m_type)
0
17324
            {
0
17325
                case value_t::null:
0
17326
                    return "null";
0
17327
                case value_t::object:
0
17328
                    return "object";
0
17329
                case value_t::array:
0
17330
                    return "array";
0
17331
                case value_t::string:
0
17332
                    return "string";
0
17333
                case value_t::boolean:
0
17334
                    return "boolean";
0
17335
                case value_t::discarded:
0
17336
                    return "discarded";
0
17337
                default:
0
17338
                    return "number";
0
17339
            }
0
17340
        }
0
17341
    }
17342
17343
17344
  private:
17345
    //////////////////////
17346
    // member variables //
17347
    //////////////////////
17348
17349
    /// the type of the current element
17350
    value_t m_type = value_t::null;
17351
17352
    /// the value of the current element
17353
    json_value m_value = {};
17354
17355
    //////////////////////////////////////////
17356
    // binary serialization/deserialization //
17357
    //////////////////////////////////////////
17358
17359
    /// @name binary serialization/deserialization support
17360
    /// @{
17361
17362
  public:
17363
    /*!
17364
    @brief create a CBOR serialization of a given JSON value
17365
17366
    Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
17367
    Binary Object Representation) serialization format. CBOR is a binary
17368
    serialization format which aims to be more compact than JSON itself, yet
17369
    more efficient to parse.
17370
17371
    The library uses the following mapping from JSON values types to
17372
    CBOR types according to the CBOR specification (RFC 7049):
17373
17374
    JSON value type | value/range                                | CBOR type                          | first byte
17375
    --------------- | ------------------------------------------ | ---------------------------------- | ---------------
17376
    null            | `null`                                     | Null                               | 0xF6
17377
    boolean         | `true`                                     | True                               | 0xF5
17378
    boolean         | `false`                                    | False                              | 0xF4
17379
    number_integer  | -9223372036854775808..-2147483649          | Negative integer (8 bytes follow)  | 0x3B
17380
    number_integer  | -2147483648..-32769                        | Negative integer (4 bytes follow)  | 0x3A
17381
    number_integer  | -32768..-129                               | Negative integer (2 bytes follow)  | 0x39
17382
    number_integer  | -128..-25                                  | Negative integer (1 byte follow)   | 0x38
17383
    number_integer  | -24..-1                                    | Negative integer                   | 0x20..0x37
17384
    number_integer  | 0..23                                      | Integer                            | 0x00..0x17
17385
    number_integer  | 24..255                                    | Unsigned integer (1 byte follow)   | 0x18
17386
    number_integer  | 256..65535                                 | Unsigned integer (2 bytes follow)  | 0x19
17387
    number_integer  | 65536..4294967295                          | Unsigned integer (4 bytes follow)  | 0x1A
17388
    number_integer  | 4294967296..18446744073709551615           | Unsigned integer (8 bytes follow)  | 0x1B
17389
    number_unsigned | 0..23                                      | Integer                            | 0x00..0x17
17390
    number_unsigned | 24..255                                    | Unsigned integer (1 byte follow)   | 0x18
17391
    number_unsigned | 256..65535                                 | Unsigned integer (2 bytes follow)  | 0x19
17392
    number_unsigned | 65536..4294967295                          | Unsigned integer (4 bytes follow)  | 0x1A
17393
    number_unsigned | 4294967296..18446744073709551615           | Unsigned integer (8 bytes follow)  | 0x1B
17394
    number_float    | *any value*                                | Double-Precision Float             | 0xFB
17395
    string          | *length*: 0..23                            | UTF-8 string                       | 0x60..0x77
17396
    string          | *length*: 23..255                          | UTF-8 string (1 byte follow)       | 0x78
17397
    string          | *length*: 256..65535                       | UTF-8 string (2 bytes follow)      | 0x79
17398
    string          | *length*: 65536..4294967295                | UTF-8 string (4 bytes follow)      | 0x7A
17399
    string          | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow)      | 0x7B
17400
    array           | *size*: 0..23                              | array                              | 0x80..0x97
17401
    array           | *size*: 23..255                            | array (1 byte follow)              | 0x98
17402
    array           | *size*: 256..65535                         | array (2 bytes follow)             | 0x99
17403
    array           | *size*: 65536..4294967295                  | array (4 bytes follow)             | 0x9A
17404
    array           | *size*: 4294967296..18446744073709551615   | array (8 bytes follow)             | 0x9B
17405
    object          | *size*: 0..23                              | map                                | 0xA0..0xB7
17406
    object          | *size*: 23..255                            | map (1 byte follow)                | 0xB8
17407
    object          | *size*: 256..65535                         | map (2 bytes follow)               | 0xB9
17408
    object          | *size*: 65536..4294967295                  | map (4 bytes follow)               | 0xBA
17409
    object          | *size*: 4294967296..18446744073709551615   | map (8 bytes follow)               | 0xBB
17410
17411
    @note The mapping is **complete** in the sense that any JSON value type
17412
          can be converted to a CBOR value.
17413
17414
    @note If NaN or Infinity are stored inside a JSON number, they are
17415
          serialized properly. This behavior differs from the @ref dump()
17416
          function which serializes NaN or Infinity to `null`.
17417
17418
    @note The following CBOR types are not used in the conversion:
17419
          - byte strings (0x40..0x5F)
17420
          - UTF-8 strings terminated by "break" (0x7F)
17421
          - arrays terminated by "break" (0x9F)
17422
          - maps terminated by "break" (0xBF)
17423
          - date/time (0xC0..0xC1)
17424
          - bignum (0xC2..0xC3)
17425
          - decimal fraction (0xC4)
17426
          - bigfloat (0xC5)
17427
          - tagged items (0xC6..0xD4, 0xD8..0xDB)
17428
          - expected conversions (0xD5..0xD7)
17429
          - simple values (0xE0..0xF3, 0xF8)
17430
          - undefined (0xF7)
17431
          - half and single-precision floats (0xF9-0xFA)
17432
          - break (0xFF)
17433
17434
    @param[in] j  JSON value to serialize
17435
    @return MessagePack serialization as byte vector
17436
17437
    @complexity Linear in the size of the JSON value @a j.
17438
17439
    @liveexample{The example shows the serialization of a JSON value to a byte
17440
    vector in CBOR format.,to_cbor}
17441
17442
    @sa http://cbor.io
17443
    @sa @ref from_cbor(detail::input_adapter, const bool strict) for the
17444
        analogous deserialization
17445
    @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
17446
    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
17447
             related UBJSON format
17448
17449
    @since version 2.0.9
17450
    */
17451
    static std::vector<uint8_t> to_cbor(const basic_json& j)
17452
    {
17453
        std::vector<uint8_t> result;
17454
        to_cbor(j, result);
17455
        return result;
17456
    }
17457
17458
    static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
17459
    {
17460
        binary_writer<uint8_t>(o).write_cbor(j);
17461
    }
17462
17463
    static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
17464
    {
17465
        binary_writer<char>(o).write_cbor(j);
17466
    }
17467
17468
    /*!
17469
    @brief create a MessagePack serialization of a given JSON value
17470
17471
    Serializes a given JSON value @a j to a byte vector using the MessagePack
17472
    serialization format. MessagePack is a binary serialization format which
17473
    aims to be more compact than JSON itself, yet more efficient to parse.
17474
17475
    The library uses the following mapping from JSON values types to
17476
    MessagePack types according to the MessagePack specification:
17477
17478
    JSON value type | value/range                       | MessagePack type | first byte
17479
    --------------- | --------------------------------- | ---------------- | ----------
17480
    null            | `null`                            | nil              | 0xC0
17481
    boolean         | `true`                            | true             | 0xC3
17482
    boolean         | `false`                           | false            | 0xC2
17483
    number_integer  | -9223372036854775808..-2147483649 | int64            | 0xD3
17484
    number_integer  | -2147483648..-32769               | int32            | 0xD2
17485
    number_integer  | -32768..-129                      | int16            | 0xD1
17486
    number_integer  | -128..-33                         | int8             | 0xD0
17487
    number_integer  | -32..-1                           | negative fixint  | 0xE0..0xFF
17488
    number_integer  | 0..127                            | positive fixint  | 0x00..0x7F
17489
    number_integer  | 128..255                          | uint 8           | 0xCC
17490
    number_integer  | 256..65535                        | uint 16          | 0xCD
17491
    number_integer  | 65536..4294967295                 | uint 32          | 0xCE
17492
    number_integer  | 4294967296..18446744073709551615  | uint 64          | 0xCF
17493
    number_unsigned | 0..127                            | positive fixint  | 0x00..0x7F
17494
    number_unsigned | 128..255                          | uint 8           | 0xCC
17495
    number_unsigned | 256..65535                        | uint 16          | 0xCD
17496
    number_unsigned | 65536..4294967295                 | uint 32          | 0xCE
17497
    number_unsigned | 4294967296..18446744073709551615  | uint 64          | 0xCF
17498
    number_float    | *any value*                       | float 64         | 0xCB
17499
    string          | *length*: 0..31                   | fixstr           | 0xA0..0xBF
17500
    string          | *length*: 32..255                 | str 8            | 0xD9
17501
    string          | *length*: 256..65535              | str 16           | 0xDA
17502
    string          | *length*: 65536..4294967295       | str 32           | 0xDB
17503
    array           | *size*: 0..15                     | fixarray         | 0x90..0x9F
17504
    array           | *size*: 16..65535                 | array 16         | 0xDC
17505
    array           | *size*: 65536..4294967295         | array 32         | 0xDD
17506
    object          | *size*: 0..15                     | fix map          | 0x80..0x8F
17507
    object          | *size*: 16..65535                 | map 16           | 0xDE
17508
    object          | *size*: 65536..4294967295         | map 32           | 0xDF
17509
17510
    @note The mapping is **complete** in the sense that any JSON value type
17511
          can be converted to a MessagePack value.
17512
17513
    @note The following values can **not** be converted to a MessagePack value:
17514
          - strings with more than 4294967295 bytes
17515
          - arrays with more than 4294967295 elements
17516
          - objects with more than 4294967295 elements
17517
17518
    @note The following MessagePack types are not used in the conversion:
17519
          - bin 8 - bin 32 (0xC4..0xC6)
17520
          - ext 8 - ext 32 (0xC7..0xC9)
17521
          - float 32 (0xCA)
17522
          - fixext 1 - fixext 16 (0xD4..0xD8)
17523
17524
    @note Any MessagePack output created @ref to_msgpack can be successfully
17525
          parsed by @ref from_msgpack.
17526
17527
    @note If NaN or Infinity are stored inside a JSON number, they are
17528
          serialized properly. This behavior differs from the @ref dump()
17529
          function which serializes NaN or Infinity to `null`.
17530
17531
    @param[in] j  JSON value to serialize
17532
    @return MessagePack serialization as byte vector
17533
17534
    @complexity Linear in the size of the JSON value @a j.
17535
17536
    @liveexample{The example shows the serialization of a JSON value to a byte
17537
    vector in MessagePack format.,to_msgpack}
17538
17539
    @sa http://msgpack.org
17540
    @sa @ref from_msgpack(const std::vector<uint8_t>&, const size_t) for the
17541
        analogous deserialization
17542
    @sa @ref to_cbor(const basic_json& for the related CBOR format
17543
    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
17544
             related UBJSON format
17545
17546
    @since version 2.0.9
17547
    */
17548
    static std::vector<uint8_t> to_msgpack(const basic_json& j)
17549
    {
17550
        std::vector<uint8_t> result;
17551
        to_msgpack(j, result);
17552
        return result;
17553
    }
17554
17555
    static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
17556
    {
17557
        binary_writer<uint8_t>(o).write_msgpack(j);
17558
    }
17559
17560
    static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
17561
    {
17562
        binary_writer<char>(o).write_msgpack(j);
17563
    }
17564
17565
    /*!
17566
    @brief create a UBJSON serialization of a given JSON value
17567
17568
    Serializes a given JSON value @a j to a byte vector using the UBJSON
17569
    (Universal Binary JSON) serialization format. UBJSON aims to be more compact
17570
    than JSON itself, yet more efficient to parse.
17571
17572
    The library uses the following mapping from JSON values types to
17573
    UBJSON types according to the UBJSON specification:
17574
17575
    JSON value type | value/range                       | UBJSON type | marker
17576
    --------------- | --------------------------------- | ----------- | ------
17577
    null            | `null`                            | null        | `Z`
17578
    boolean         | `true`                            | true        | `T`
17579
    boolean         | `false`                           | false       | `F`
17580
    number_integer  | -9223372036854775808..-2147483649 | int64       | `L`
17581
    number_integer  | -2147483648..-32769               | int32       | `l`
17582
    number_integer  | -32768..-129                      | int16       | `I`
17583
    number_integer  | -128..127                         | int8        | `i`
17584
    number_integer  | 128..255                          | uint8       | `U`
17585
    number_integer  | 256..32767                        | int16       | `I`
17586
    number_integer  | 32768..2147483647                 | int32       | `l`
17587
    number_integer  | 2147483648..9223372036854775807   | int64       | `L`
17588
    number_unsigned | 0..127                            | int8        | `i`
17589
    number_unsigned | 128..255                          | uint8       | `U`
17590
    number_unsigned | 256..32767                        | int16       | `I`
17591
    number_unsigned | 32768..2147483647                 | int32       | `l`
17592
    number_unsigned | 2147483648..9223372036854775807   | int64       | `L`
17593
    number_float    | *any value*                       | float64     | `D`
17594
    string          | *with shortest length indicator*  | string      | `S`
17595
    array           | *see notes on optimized format*   | array       | `[`
17596
    object          | *see notes on optimized format*   | map         | `{`
17597
17598
    @note The mapping is **complete** in the sense that any JSON value type
17599
          can be converted to a UBJSON value.
17600
17601
    @note The following values can **not** be converted to a UBJSON value:
17602
          - strings with more than 9223372036854775807 bytes (theoretical)
17603
          - unsigned integer numbers above 9223372036854775807
17604
17605
    @note The following markers are not used in the conversion:
17606
          - `Z`: no-op values are not created.
17607
          - `C`: single-byte strings are serialized with `S` markers.
17608
17609
    @note Any UBJSON output created @ref to_ubjson can be successfully parsed
17610
          by @ref from_ubjson.
17611
17612
    @note If NaN or Infinity are stored inside a JSON number, they are
17613
          serialized properly. This behavior differs from the @ref dump()
17614
          function which serializes NaN or Infinity to `null`.
17615
17616
    @note The optimized formats for containers are supported: Parameter
17617
          @a use_size adds size information to the beginning of a container and
17618
          removes the closing marker. Parameter @a use_type further checks
17619
          whether all elements of a container have the same type and adds the
17620
          type marker to the beginning of the container. The @a use_type
17621
          parameter must only be used together with @a use_size = true. Note
17622
          that @a use_size = true alone may result in larger representations -
17623
          the benefit of this parameter is that the receiving side is
17624
          immediately informed on the number of elements of the container.
17625
17626
    @param[in] j  JSON value to serialize
17627
    @param[in] use_size  whether to add size annotations to container types
17628
    @param[in] use_type  whether to add type annotations to container types
17629
                         (must be combined with @a use_size = true)
17630
    @return UBJSON serialization as byte vector
17631
17632
    @complexity Linear in the size of the JSON value @a j.
17633
17634
    @liveexample{The example shows the serialization of a JSON value to a byte
17635
    vector in UBJSON format.,to_ubjson}
17636
17637
    @sa http://ubjson.org
17638
    @sa @ref from_ubjson(detail::input_adapter, const bool strict) for the
17639
        analogous deserialization
17640
    @sa @ref to_cbor(const basic_json& for the related CBOR format
17641
    @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
17642
17643
    @since version 3.1.0
17644
    */
17645
    static std::vector<uint8_t> to_ubjson(const basic_json& j,
17646
                                          const bool use_size = false,
17647
                                          const bool use_type = false)
17648
    {
17649
        std::vector<uint8_t> result;
17650
        to_ubjson(j, result, use_size, use_type);
17651
        return result;
17652
    }
17653
17654
    static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
17655
                          const bool use_size = false, const bool use_type = false)
17656
    {
17657
        binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
17658
    }
17659
17660
    static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
17661
                          const bool use_size = false, const bool use_type = false)
17662
    {
17663
        binary_writer<char>(o).write_ubjson(j, use_size, use_type);
17664
    }
17665
17666
    /*!
17667
    @brief create a JSON value from an input in CBOR format
17668
17669
    Deserializes a given input @a i to a JSON value using the CBOR (Concise
17670
    Binary Object Representation) serialization format.
17671
17672
    The library maps CBOR types to JSON value types as follows:
17673
17674
    CBOR type              | JSON value type | first byte
17675
    ---------------------- | --------------- | ----------
17676
    Integer                | number_unsigned | 0x00..0x17
17677
    Unsigned integer       | number_unsigned | 0x18
17678
    Unsigned integer       | number_unsigned | 0x19
17679
    Unsigned integer       | number_unsigned | 0x1A
17680
    Unsigned integer       | number_unsigned | 0x1B
17681
    Negative integer       | number_integer  | 0x20..0x37
17682
    Negative integer       | number_integer  | 0x38
17683
    Negative integer       | number_integer  | 0x39
17684
    Negative integer       | number_integer  | 0x3A
17685
    Negative integer       | number_integer  | 0x3B
17686
    Negative integer       | number_integer  | 0x40..0x57
17687
    UTF-8 string           | string          | 0x60..0x77
17688
    UTF-8 string           | string          | 0x78
17689
    UTF-8 string           | string          | 0x79
17690
    UTF-8 string           | string          | 0x7A
17691
    UTF-8 string           | string          | 0x7B
17692
    UTF-8 string           | string          | 0x7F
17693
    array                  | array           | 0x80..0x97
17694
    array                  | array           | 0x98
17695
    array                  | array           | 0x99
17696
    array                  | array           | 0x9A
17697
    array                  | array           | 0x9B
17698
    array                  | array           | 0x9F
17699
    map                    | object          | 0xA0..0xB7
17700
    map                    | object          | 0xB8
17701
    map                    | object          | 0xB9
17702
    map                    | object          | 0xBA
17703
    map                    | object          | 0xBB
17704
    map                    | object          | 0xBF
17705
    False                  | `false`         | 0xF4
17706
    True                   | `true`          | 0xF5
17707
    Nill                   | `null`          | 0xF6
17708
    Half-Precision Float   | number_float    | 0xF9
17709
    Single-Precision Float | number_float    | 0xFA
17710
    Double-Precision Float | number_float    | 0xFB
17711
17712
    @warning The mapping is **incomplete** in the sense that not all CBOR
17713
             types can be converted to a JSON value. The following CBOR types
17714
             are not supported and will yield parse errors (parse_error.112):
17715
             - byte strings (0x40..0x5F)
17716
             - date/time (0xC0..0xC1)
17717
             - bignum (0xC2..0xC3)
17718
             - decimal fraction (0xC4)
17719
             - bigfloat (0xC5)
17720
             - tagged items (0xC6..0xD4, 0xD8..0xDB)
17721
             - expected conversions (0xD5..0xD7)
17722
             - simple values (0xE0..0xF3, 0xF8)
17723
             - undefined (0xF7)
17724
17725
    @warning CBOR allows map keys of any type, whereas JSON only allows
17726
             strings as keys in object values. Therefore, CBOR maps with keys
17727
             other than UTF-8 strings are rejected (parse_error.113).
17728
17729
    @note Any CBOR output created @ref to_cbor can be successfully parsed by
17730
          @ref from_cbor.
17731
17732
    @param[in] i  an input in CBOR format convertible to an input adapter
17733
    @param[in] strict  whether to expect the input to be consumed until EOF
17734
                       (true by default)
17735
    @param[in] allow_exceptions  whether to throw exceptions in case of a
17736
    parse error (optional, true by default)
17737
17738
    @return deserialized JSON value
17739
17740
    @throw parse_error.110 if the given input ends prematurely or the end of
17741
    file was not reached when @a strict was set to true
17742
    @throw parse_error.112 if unsupported features from CBOR were
17743
    used in the given input @a v or if the input is not valid CBOR
17744
    @throw parse_error.113 if a string was expected as map key, but not found
17745
17746
    @complexity Linear in the size of the input @a i.
17747
17748
    @liveexample{The example shows the deserialization of a byte vector in CBOR
17749
    format to a JSON value.,from_cbor}
17750
17751
    @sa http://cbor.io
17752
    @sa @ref to_cbor(const basic_json&) for the analogous serialization
17753
    @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for the
17754
        related MessagePack format
17755
    @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for the
17756
        related UBJSON format
17757
17758
    @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
17759
           consume input adapters, removed start_index parameter, and added
17760
           @a strict parameter since 3.0.0; added @allow_exceptions parameter
17761
           since 3.2.0
17762
    */
17763
    static basic_json from_cbor(detail::input_adapter&& i,
17764
                                const bool strict = true,
17765
                                const bool allow_exceptions = true)
17766
    {
17767
        basic_json result;
17768
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17769
        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict);
17770
        return res ? result : basic_json(value_t::discarded);
17771
    }
17772
17773
    /*!
17774
    @copydoc from_cbor(detail::input_adapter, const bool, const bool)
17775
    */
17776
    template<typename A1, typename A2,
17777
             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
17778
    static basic_json from_cbor(A1 && a1, A2 && a2,
17779
                                const bool strict = true,
17780
                                const bool allow_exceptions = true)
17781
    {
17782
        basic_json result;
17783
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17784
        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict);
17785
        return res ? result : basic_json(value_t::discarded);
17786
    }
17787
17788
    /*!
17789
    @brief create a JSON value from an input in MessagePack format
17790
17791
    Deserializes a given input @a i to a JSON value using the MessagePack
17792
    serialization format.
17793
17794
    The library maps MessagePack types to JSON value types as follows:
17795
17796
    MessagePack type | JSON value type | first byte
17797
    ---------------- | --------------- | ----------
17798
    positive fixint  | number_unsigned | 0x00..0x7F
17799
    fixmap           | object          | 0x80..0x8F
17800
    fixarray         | array           | 0x90..0x9F
17801
    fixstr           | string          | 0xA0..0xBF
17802
    nil              | `null`          | 0xC0
17803
    false            | `false`         | 0xC2
17804
    true             | `true`          | 0xC3
17805
    float 32         | number_float    | 0xCA
17806
    float 64         | number_float    | 0xCB
17807
    uint 8           | number_unsigned | 0xCC
17808
    uint 16          | number_unsigned | 0xCD
17809
    uint 32          | number_unsigned | 0xCE
17810
    uint 64          | number_unsigned | 0xCF
17811
    int 8            | number_integer  | 0xD0
17812
    int 16           | number_integer  | 0xD1
17813
    int 32           | number_integer  | 0xD2
17814
    int 64           | number_integer  | 0xD3
17815
    str 8            | string          | 0xD9
17816
    str 16           | string          | 0xDA
17817
    str 32           | string          | 0xDB
17818
    array 16         | array           | 0xDC
17819
    array 32         | array           | 0xDD
17820
    map 16           | object          | 0xDE
17821
    map 32           | object          | 0xDF
17822
    negative fixint  | number_integer  | 0xE0-0xFF
17823
17824
    @warning The mapping is **incomplete** in the sense that not all
17825
             MessagePack types can be converted to a JSON value. The following
17826
             MessagePack types are not supported and will yield parse errors:
17827
              - bin 8 - bin 32 (0xC4..0xC6)
17828
              - ext 8 - ext 32 (0xC7..0xC9)
17829
              - fixext 1 - fixext 16 (0xD4..0xD8)
17830
17831
    @note Any MessagePack output created @ref to_msgpack can be successfully
17832
          parsed by @ref from_msgpack.
17833
17834
    @param[in] i  an input in MessagePack format convertible to an input
17835
                  adapter
17836
    @param[in] strict  whether to expect the input to be consumed until EOF
17837
                       (true by default)
17838
    @param[in] allow_exceptions  whether to throw exceptions in case of a
17839
    parse error (optional, true by default)
17840
17841
    @return deserialized JSON value
17842
17843
    @throw parse_error.110 if the given input ends prematurely or the end of
17844
    file was not reached when @a strict was set to true
17845
    @throw parse_error.112 if unsupported features from MessagePack were
17846
    used in the given input @a i or if the input is not valid MessagePack
17847
    @throw parse_error.113 if a string was expected as map key, but not found
17848
17849
    @complexity Linear in the size of the input @a i.
17850
17851
    @liveexample{The example shows the deserialization of a byte vector in
17852
    MessagePack format to a JSON value.,from_msgpack}
17853
17854
    @sa http://msgpack.org
17855
    @sa @ref to_msgpack(const basic_json&) for the analogous serialization
17856
    @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the
17857
        related CBOR format
17858
    @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for
17859
        the related UBJSON format
17860
17861
    @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
17862
           consume input adapters, removed start_index parameter, and added
17863
           @a strict parameter since 3.0.0; added @allow_exceptions parameter
17864
           since 3.2.0
17865
    */
17866
    static basic_json from_msgpack(detail::input_adapter&& i,
17867
                                   const bool strict = true,
17868
                                   const bool allow_exceptions = true)
17869
    {
17870
        basic_json result;
17871
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17872
        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict);
17873
        return res ? result : basic_json(value_t::discarded);
17874
    }
17875
17876
    /*!
17877
    @copydoc from_msgpack(detail::input_adapter, const bool, const bool)
17878
    */
17879
    template<typename A1, typename A2,
17880
             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
17881
    static basic_json from_msgpack(A1 && a1, A2 && a2,
17882
                                   const bool strict = true,
17883
                                   const bool allow_exceptions = true)
17884
    {
17885
        basic_json result;
17886
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17887
        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict);
17888
        return res ? result : basic_json(value_t::discarded);
17889
    }
17890
17891
    /*!
17892
    @brief create a JSON value from an input in UBJSON format
17893
17894
    Deserializes a given input @a i to a JSON value using the UBJSON (Universal
17895
    Binary JSON) serialization format.
17896
17897
    The library maps UBJSON types to JSON value types as follows:
17898
17899
    UBJSON type | JSON value type                         | marker
17900
    ----------- | --------------------------------------- | ------
17901
    no-op       | *no value, next value is read*          | `N`
17902
    null        | `null`                                  | `Z`
17903
    false       | `false`                                 | `F`
17904
    true        | `true`                                  | `T`
17905
    float32     | number_float                            | `d`
17906
    float64     | number_float                            | `D`
17907
    uint8       | number_unsigned                         | `U`
17908
    int8        | number_integer                          | `i`
17909
    int16       | number_integer                          | `I`
17910
    int32       | number_integer                          | `l`
17911
    int64       | number_integer                          | `L`
17912
    string      | string                                  | `S`
17913
    char        | string                                  | `C`
17914
    array       | array (optimized values are supported)  | `[`
17915
    object      | object (optimized values are supported) | `{`
17916
17917
    @note The mapping is **complete** in the sense that any UBJSON value can
17918
          be converted to a JSON value.
17919
17920
    @param[in] i  an input in UBJSON format convertible to an input adapter
17921
    @param[in] strict  whether to expect the input to be consumed until EOF
17922
                       (true by default)
17923
    @param[in] allow_exceptions  whether to throw exceptions in case of a
17924
    parse error (optional, true by default)
17925
17926
    @return deserialized JSON value
17927
17928
    @throw parse_error.110 if the given input ends prematurely or the end of
17929
    file was not reached when @a strict was set to true
17930
    @throw parse_error.112 if a parse error occurs
17931
    @throw parse_error.113 if a string could not be parsed successfully
17932
17933
    @complexity Linear in the size of the input @a i.
17934
17935
    @liveexample{The example shows the deserialization of a byte vector in
17936
    UBJSON format to a JSON value.,from_ubjson}
17937
17938
    @sa http://ubjson.org
17939
    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
17940
             analogous serialization
17941
    @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the
17942
        related CBOR format
17943
    @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for
17944
        the related MessagePack format
17945
17946
    @since version 3.1.0; added @allow_exceptions parameter since 3.2.0
17947
    */
17948
    static basic_json from_ubjson(detail::input_adapter&& i,
17949
                                  const bool strict = true,
17950
                                  const bool allow_exceptions = true)
17951
    {
17952
        basic_json result;
17953
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17954
        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict);
17955
        return res ? result : basic_json(value_t::discarded);
17956
    }
17957
17958
    /*!
17959
    @copydoc from_ubjson(detail::input_adapter, const bool, const bool)
17960
    */
17961
    template<typename A1, typename A2,
17962
             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
17963
    static basic_json from_ubjson(A1 && a1, A2 && a2,
17964
                                  const bool strict = true,
17965
                                  const bool allow_exceptions = true)
17966
    {
17967
        basic_json result;
17968
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17969
        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict);
17970
        return res ? result : basic_json(value_t::discarded);
17971
    }
17972
17973
    /// @}
17974
17975
    //////////////////////////
17976
    // JSON Pointer support //
17977
    //////////////////////////
17978
17979
    /// @name JSON Pointer functions
17980
    /// @{
17981
17982
    /*!
17983
    @brief access specified element via JSON Pointer
17984
17985
    Uses a JSON pointer to retrieve a reference to the respective JSON value.
17986
    No bound checking is performed. Similar to @ref operator[](const typename
17987
    object_t::key_type&), `null` values are created in arrays and objects if
17988
    necessary.
17989
17990
    In particular:
17991
    - If the JSON pointer points to an object key that does not exist, it
17992
      is created an filled with a `null` value before a reference to it
17993
      is returned.
17994
    - If the JSON pointer points to an array index that does not exist, it
17995
      is created an filled with a `null` value before a reference to it
17996
      is returned. All indices between the current maximum and the given
17997
      index are also filled with `null`.
17998
    - The special value `-` is treated as a synonym for the index past the
17999
      end.
18000
18001
    @param[in] ptr  a JSON pointer
18002
18003
    @return reference to the element pointed to by @a ptr
18004
18005
    @complexity Constant.
18006
18007
    @throw parse_error.106   if an array index begins with '0'
18008
    @throw parse_error.109   if an array index was not a number
18009
    @throw out_of_range.404  if the JSON pointer can not be resolved
18010
18011
    @liveexample{The behavior is shown in the example.,operatorjson_pointer}
18012
18013
    @since version 2.0.0
18014
    */
18015
    reference operator[](const json_pointer& ptr)
18016
    {
18017
        return ptr.get_unchecked(this);
18018
    }
18019
18020
    /*!
18021
    @brief access specified element via JSON Pointer
18022
18023
    Uses a JSON pointer to retrieve a reference to the respective JSON value.
18024
    No bound checking is performed. The function does not change the JSON
18025
    value; no `null` values are created. In particular, the the special value
18026
    `-` yields an exception.
18027
18028
    @param[in] ptr  JSON pointer to the desired element
18029
18030
    @return const reference to the element pointed to by @a ptr
18031
18032
    @complexity Constant.
18033
18034
    @throw parse_error.106   if an array index begins with '0'
18035
    @throw parse_error.109   if an array index was not a number
18036
    @throw out_of_range.402  if the array index '-' is used
18037
    @throw out_of_range.404  if the JSON pointer can not be resolved
18038
18039
    @liveexample{The behavior is shown in the example.,operatorjson_pointer_const}
18040
18041
    @since version 2.0.0
18042
    */
18043
    const_reference operator[](const json_pointer& ptr) const
18044
    {
18045
        return ptr.get_unchecked(this);
18046
    }
18047
18048
    /*!
18049
    @brief access specified element via JSON Pointer
18050
18051
    Returns a reference to the element at with specified JSON pointer @a ptr,
18052
    with bounds checking.
18053
18054
    @param[in] ptr  JSON pointer to the desired element
18055
18056
    @return reference to the element pointed to by @a ptr
18057
18058
    @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
18059
    begins with '0'. See example below.
18060
18061
    @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
18062
    is not a number. See example below.
18063
18064
    @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
18065
    is out of range. See example below.
18066
18067
    @throw out_of_range.402 if the array index '-' is used in the passed JSON
18068
    pointer @a ptr. As `at` provides checked access (and no elements are
18069
    implicitly inserted), the index '-' is always invalid. See example below.
18070
18071
    @throw out_of_range.403 if the JSON pointer describes a key of an object
18072
    which cannot be found. See example below.
18073
18074
    @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
18075
    See example below.
18076
18077
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18078
    changes in the JSON value.
18079
18080
    @complexity Constant.
18081
18082
    @since version 2.0.0
18083
18084
    @liveexample{The behavior is shown in the example.,at_json_pointer}
18085
    */
18086
    reference at(const json_pointer& ptr)
18087
    {
18088
        return ptr.get_checked(this);
18089
    }
18090
18091
    /*!
18092
    @brief access specified element via JSON Pointer
18093
18094
    Returns a const reference to the element at with specified JSON pointer @a
18095
    ptr, with bounds checking.
18096
18097
    @param[in] ptr  JSON pointer to the desired element
18098
18099
    @return reference to the element pointed to by @a ptr
18100
18101
    @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
18102
    begins with '0'. See example below.
18103
18104
    @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
18105
    is not a number. See example below.
18106
18107
    @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
18108
    is out of range. See example below.
18109
18110
    @throw out_of_range.402 if the array index '-' is used in the passed JSON
18111
    pointer @a ptr. As `at` provides checked access (and no elements are
18112
    implicitly inserted), the index '-' is always invalid. See example below.
18113
18114
    @throw out_of_range.403 if the JSON pointer describes a key of an object
18115
    which cannot be found. See example below.
18116
18117
    @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
18118
    See example below.
18119
18120
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18121
    changes in the JSON value.
18122
18123
    @complexity Constant.
18124
18125
    @since version 2.0.0
18126
18127
    @liveexample{The behavior is shown in the example.,at_json_pointer_const}
18128
    */
18129
    const_reference at(const json_pointer& ptr) const
18130
    {
18131
        return ptr.get_checked(this);
18132
    }
18133
18134
    /*!
18135
    @brief return flattened JSON value
18136
18137
    The function creates a JSON object whose keys are JSON pointers (see [RFC
18138
    6901](https://tools.ietf.org/html/rfc6901)) and whose values are all
18139
    primitive. The original JSON value can be restored using the @ref
18140
    unflatten() function.
18141
18142
    @return an object that maps JSON pointers to primitive values
18143
18144
    @note Empty objects and arrays are flattened to `null` and will not be
18145
          reconstructed correctly by the @ref unflatten() function.
18146
18147
    @complexity Linear in the size the JSON value.
18148
18149
    @liveexample{The following code shows how a JSON object is flattened to an
18150
    object whose keys consist of JSON pointers.,flatten}
18151
18152
    @sa @ref unflatten() for the reverse function
18153
18154
    @since version 2.0.0
18155
    */
18156
    basic_json flatten() const
18157
    {
18158
        basic_json result(value_t::object);
18159
        json_pointer::flatten("", *this, result);
18160
        return result;
18161
    }
18162
18163
    /*!
18164
    @brief unflatten a previously flattened JSON value
18165
18166
    The function restores the arbitrary nesting of a JSON value that has been
18167
    flattened before using the @ref flatten() function. The JSON value must
18168
    meet certain constraints:
18169
    1. The value must be an object.
18170
    2. The keys must be JSON pointers (see
18171
       [RFC 6901](https://tools.ietf.org/html/rfc6901))
18172
    3. The mapped values must be primitive JSON types.
18173
18174
    @return the original JSON from a flattened version
18175
18176
    @note Empty objects and arrays are flattened by @ref flatten() to `null`
18177
          values and can not unflattened to their original type. Apart from
18178
          this example, for a JSON value `j`, the following is always true:
18179
          `j == j.flatten().unflatten()`.
18180
18181
    @complexity Linear in the size the JSON value.
18182
18183
    @throw type_error.314  if value is not an object
18184
    @throw type_error.315  if object values are not primitive
18185
18186
    @liveexample{The following code shows how a flattened JSON object is
18187
    unflattened into the original nested JSON object.,unflatten}
18188
18189
    @sa @ref flatten() for the reverse function
18190
18191
    @since version 2.0.0
18192
    */
18193
    basic_json unflatten() const
18194
    {
18195
        return json_pointer::unflatten(*this);
18196
    }
18197
18198
    /// @}
18199
18200
    //////////////////////////
18201
    // JSON Patch functions //
18202
    //////////////////////////
18203
18204
    /// @name JSON Patch functions
18205
    /// @{
18206
18207
    /*!
18208
    @brief applies a JSON patch
18209
18210
    [JSON Patch](http://jsonpatch.com) defines a JSON document structure for
18211
    expressing a sequence of operations to apply to a JSON) document. With
18212
    this function, a JSON Patch is applied to the current JSON value by
18213
    executing all operations from the patch.
18214
18215
    @param[in] json_patch  JSON patch document
18216
    @return patched document
18217
18218
    @note The application of a patch is atomic: Either all operations succeed
18219
          and the patched document is returned or an exception is thrown. In
18220
          any case, the original value is not changed: the patch is applied
18221
          to a copy of the value.
18222
18223
    @throw parse_error.104 if the JSON patch does not consist of an array of
18224
    objects
18225
18226
    @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory
18227
    attributes are missing); example: `"operation add must have member path"`
18228
18229
    @throw out_of_range.401 if an array index is out of range.
18230
18231
    @throw out_of_range.403 if a JSON pointer inside the patch could not be
18232
    resolved successfully in the current JSON value; example: `"key baz not
18233
    found"`
18234
18235
    @throw out_of_range.405 if JSON pointer has no parent ("add", "remove",
18236
    "move")
18237
18238
    @throw other_error.501 if "test" operation was unsuccessful
18239
18240
    @complexity Linear in the size of the JSON value and the length of the
18241
    JSON patch. As usually only a fraction of the JSON value is affected by
18242
    the patch, the complexity can usually be neglected.
18243
18244
    @liveexample{The following code shows how a JSON patch is applied to a
18245
    value.,patch}
18246
18247
    @sa @ref diff -- create a JSON patch by comparing two JSON values
18248
18249
    @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
18250
    @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)
18251
18252
    @since version 2.0.0
18253
    */
18254
    basic_json patch(const basic_json& json_patch) const
18255
    {
18256
        // make a working copy to apply the patch to
18257
        basic_json result = *this;
18258
18259
        // the valid JSON Patch operations
18260
        enum class patch_operations {add, remove, replace, move, copy, test, invalid};
18261
18262
        const auto get_op = [](const std::string & op)
18263
        {
18264
            if (op == "add")
18265
            {
18266
                return patch_operations::add;
18267
            }
18268
            if (op == "remove")
18269
            {
18270
                return patch_operations::remove;
18271
            }
18272
            if (op == "replace")
18273
            {
18274
                return patch_operations::replace;
18275
            }
18276
            if (op == "move")
18277
            {
18278
                return patch_operations::move;
18279
            }
18280
            if (op == "copy")
18281
            {
18282
                return patch_operations::copy;
18283
            }
18284
            if (op == "test")
18285
            {
18286
                return patch_operations::test;
18287
            }
18288
18289
            return patch_operations::invalid;
18290
        };
18291
18292
        // wrapper for "add" operation; add value at ptr
18293
        const auto operation_add = [&result](json_pointer & ptr, basic_json val)
18294
        {
18295
            // adding to the root of the target document means replacing it
18296
            if (ptr.is_root())
18297
            {
18298
                result = val;
18299
            }
18300
            else
18301
            {
18302
                // make sure the top element of the pointer exists
18303
                json_pointer top_pointer = ptr.top();
18304
                if (top_pointer != ptr)
18305
                {
18306
                    result.at(top_pointer);
18307
                }
18308
18309
                // get reference to parent of JSON pointer ptr
18310
                const auto last_path = ptr.pop_back();
18311
                basic_json& parent = result[ptr];
18312
18313
                switch (parent.m_type)
18314
                {
18315
                    case value_t::null:
18316
                    case value_t::object:
18317
                    {
18318
                        // use operator[] to add value
18319
                        parent[last_path] = val;
18320
                        break;
18321
                    }
18322
18323
                    case value_t::array:
18324
                    {
18325
                        if (last_path == "-")
18326
                        {
18327
                            // special case: append to back
18328
                            parent.push_back(val);
18329
                        }
18330
                        else
18331
                        {
18332
                            const auto idx = json_pointer::array_index(last_path);
18333
                            if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
18334
                            {
18335
                                // avoid undefined behavior
18336
                                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
18337
                            }
18338
                            else
18339
                            {
18340
                                // default case: insert add offset
18341
                                parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
18342
                            }
18343
                        }
18344
                        break;
18345
                    }
18346
18347
                    // LCOV_EXCL_START
18348
                    default:
18349
                    {
18350
                        // if there exists a parent it cannot be primitive
18351
                        assert(false);
18352
                    }
18353
                        // LCOV_EXCL_STOP
18354
                }
18355
            }
18356
        };
18357
18358
        // wrapper for "remove" operation; remove value at ptr
18359
        const auto operation_remove = [&result](json_pointer & ptr)
18360
        {
18361
            // get reference to parent of JSON pointer ptr
18362
            const auto last_path = ptr.pop_back();
18363
            basic_json& parent = result.at(ptr);
18364
18365
            // remove child
18366
            if (parent.is_object())
18367
            {
18368
                // perform range check
18369
                auto it = parent.find(last_path);
18370
                if (JSON_LIKELY(it != parent.end()))
18371
                {
18372
                    parent.erase(it);
18373
                }
18374
                else
18375
                {
18376
                    JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
18377
                }
18378
            }
18379
            else if (parent.is_array())
18380
            {
18381
                // note erase performs range check
18382
                parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
18383
            }
18384
        };
18385
18386
        // type check: top level value must be an array
18387
        if (JSON_UNLIKELY(not json_patch.is_array()))
18388
        {
18389
            JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
18390
        }
18391
18392
        // iterate and apply the operations
18393
        for (const auto& val : json_patch)
18394
        {
18395
            // wrapper to get a value for an operation
18396
            const auto get_value = [&val](const std::string & op,
18397
                                          const std::string & member,
18398
                                          bool string_type) -> basic_json &
18399
            {
18400
                // find value
18401
                auto it = val.m_value.object->find(member);
18402
18403
                // context-sensitive error message
18404
                const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
18405
18406
                // check if desired value is present
18407
                if (JSON_UNLIKELY(it == val.m_value.object->end()))
18408
                {
18409
                    JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
18410
                }
18411
18412
                // check if result is of type string
18413
                if (JSON_UNLIKELY(string_type and not it->second.is_string()))
18414
                {
18415
                    JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
18416
                }
18417
18418
                // no error: return value
18419
                return it->second;
18420
            };
18421
18422
            // type check: every element of the array must be an object
18423
            if (JSON_UNLIKELY(not val.is_object()))
18424
            {
18425
                JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
18426
            }
18427
18428
            // collect mandatory members
18429
            const std::string op = get_value("op", "op", true);
18430
            const std::string path = get_value(op, "path", true);
18431
            json_pointer ptr(path);
18432
18433
            switch (get_op(op))
18434
            {
18435
                case patch_operations::add:
18436
                {
18437
                    operation_add(ptr, get_value("add", "value", false));
18438
                    break;
18439
                }
18440
18441
                case patch_operations::remove:
18442
                {
18443
                    operation_remove(ptr);
18444
                    break;
18445
                }
18446
18447
                case patch_operations::replace:
18448
                {
18449
                    // the "path" location must exist - use at()
18450
                    result.at(ptr) = get_value("replace", "value", false);
18451
                    break;
18452
                }
18453
18454
                case patch_operations::move:
18455
                {
18456
                    const std::string from_path = get_value("move", "from", true);
18457
                    json_pointer from_ptr(from_path);
18458
18459
                    // the "from" location must exist - use at()
18460
                    basic_json v = result.at(from_ptr);
18461
18462
                    // The move operation is functionally identical to a
18463
                    // "remove" operation on the "from" location, followed
18464
                    // immediately by an "add" operation at the target
18465
                    // location with the value that was just removed.
18466
                    operation_remove(from_ptr);
18467
                    operation_add(ptr, v);
18468
                    break;
18469
                }
18470
18471
                case patch_operations::copy:
18472
                {
18473
                    const std::string from_path = get_value("copy", "from", true);
18474
                    const json_pointer from_ptr(from_path);
18475
18476
                    // the "from" location must exist - use at()
18477
                    basic_json v = result.at(from_ptr);
18478
18479
                    // The copy is functionally identical to an "add"
18480
                    // operation at the target location using the value
18481
                    // specified in the "from" member.
18482
                    operation_add(ptr, v);
18483
                    break;
18484
                }
18485
18486
                case patch_operations::test:
18487
                {
18488
                    bool success = false;
18489
                    JSON_TRY
18490
                    {
18491
                        // check if "value" matches the one at "path"
18492
                        // the "path" location must exist - use at()
18493
                        success = (result.at(ptr) == get_value("test", "value", false));
18494
                    }
18495
                    JSON_INTERNAL_CATCH (out_of_range&)
18496
                    {
18497
                        // ignore out of range errors: success remains false
18498
                    }
18499
18500
                    // throw an exception if test fails
18501
                    if (JSON_UNLIKELY(not success))
18502
                    {
18503
                        JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
18504
                    }
18505
18506
                    break;
18507
                }
18508
18509
                case patch_operations::invalid:
18510
                {
18511
                    // op must be "add", "remove", "replace", "move", "copy", or
18512
                    // "test"
18513
                    JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
18514
                }
18515
            }
18516
        }
18517
18518
        return result;
18519
    }
18520
18521
    /*!
18522
    @brief creates a diff as a JSON patch
18523
18524
    Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can
18525
    be changed into the value @a target by calling @ref patch function.
18526
18527
    @invariant For two JSON values @a source and @a target, the following code
18528
    yields always `true`:
18529
    @code {.cpp}
18530
    source.patch(diff(source, target)) == target;
18531
    @endcode
18532
18533
    @note Currently, only `remove`, `add`, and `replace` operations are
18534
          generated.
18535
18536
    @param[in] source  JSON value to compare from
18537
    @param[in] target  JSON value to compare against
18538
    @param[in] path    helper value to create JSON pointers
18539
18540
    @return a JSON patch to convert the @a source to @a target
18541
18542
    @complexity Linear in the lengths of @a source and @a target.
18543
18544
    @liveexample{The following code shows how a JSON patch is created as a
18545
    diff for two JSON values.,diff}
18546
18547
    @sa @ref patch -- apply a JSON patch
18548
    @sa @ref merge_patch -- apply a JSON Merge Patch
18549
18550
    @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
18551
18552
    @since version 2.0.0
18553
    */
18554
    static basic_json diff(const basic_json& source, const basic_json& target,
18555
                           const std::string& path = "")
18556
    {
18557
        // the patch
18558
        basic_json result(value_t::array);
18559
18560
        // if the values are the same, return empty patch
18561
        if (source == target)
18562
        {
18563
            return result;
18564
        }
18565
18566
        if (source.type() != target.type())
18567
        {
18568
            // different types: replace value
18569
            result.push_back(
18570
            {
18571
                {"op", "replace"}, {"path", path}, {"value", target}
18572
            });
18573
        }
18574
        else
18575
        {
18576
            switch (source.type())
18577
            {
18578
                case value_t::array:
18579
                {
18580
                    // first pass: traverse common elements
18581
                    std::size_t i = 0;
18582
                    while (i < source.size() and i < target.size())
18583
                    {
18584
                        // recursive call to compare array values at index i
18585
                        auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
18586
                        result.insert(result.end(), temp_diff.begin(), temp_diff.end());
18587
                        ++i;
18588
                    }
18589
18590
                    // i now reached the end of at least one array
18591
                    // in a second pass, traverse the remaining elements
18592
18593
                    // remove my remaining elements
18594
                    const auto end_index = static_cast<difference_type>(result.size());
18595
                    while (i < source.size())
18596
                    {
18597
                        // add operations in reverse order to avoid invalid
18598
                        // indices
18599
                        result.insert(result.begin() + end_index, object(
18600
                        {
18601
                            {"op", "remove"},
18602
                            {"path", path + "/" + std::to_string(i)}
18603
                        }));
18604
                        ++i;
18605
                    }
18606
18607
                    // add other remaining elements
18608
                    while (i < target.size())
18609
                    {
18610
                        result.push_back(
18611
                        {
18612
                            {"op", "add"},
18613
                            {"path", path + "/" + std::to_string(i)},
18614
                            {"value", target[i]}
18615
                        });
18616
                        ++i;
18617
                    }
18618
18619
                    break;
18620
                }
18621
18622
                case value_t::object:
18623
                {
18624
                    // first pass: traverse this object's elements
18625
                    for (auto it = source.cbegin(); it != source.cend(); ++it)
18626
                    {
18627
                        // escape the key name to be used in a JSON patch
18628
                        const auto key = json_pointer::escape(it.key());
18629
18630
                        if (target.find(it.key()) != target.end())
18631
                        {
18632
                            // recursive call to compare object values at key it
18633
                            auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
18634
                            result.insert(result.end(), temp_diff.begin(), temp_diff.end());
18635
                        }
18636
                        else
18637
                        {
18638
                            // found a key that is not in o -> remove it
18639
                            result.push_back(object(
18640
                            {
18641
                                {"op", "remove"}, {"path", path + "/" + key}
18642
                            }));
18643
                        }
18644
                    }
18645
18646
                    // second pass: traverse other object's elements
18647
                    for (auto it = target.cbegin(); it != target.cend(); ++it)
18648
                    {
18649
                        if (source.find(it.key()) == source.end())
18650
                        {
18651
                            // found a key that is not in this -> add it
18652
                            const auto key = json_pointer::escape(it.key());
18653
                            result.push_back(
18654
                            {
18655
                                {"op", "add"}, {"path", path + "/" + key},
18656
                                {"value", it.value()}
18657
                            });
18658
                        }
18659
                    }
18660
18661
                    break;
18662
                }
18663
18664
                default:
18665
                {
18666
                    // both primitive type: replace value
18667
                    result.push_back(
18668
                    {
18669
                        {"op", "replace"}, {"path", path}, {"value", target}
18670
                    });
18671
                    break;
18672
                }
18673
            }
18674
        }
18675
18676
        return result;
18677
    }
18678
18679
    /// @}
18680
18681
    ////////////////////////////////
18682
    // JSON Merge Patch functions //
18683
    ////////////////////////////////
18684
18685
    /// @name JSON Merge Patch functions
18686
    /// @{
18687
18688
    /*!
18689
    @brief applies a JSON Merge Patch
18690
18691
    The merge patch format is primarily intended for use with the HTTP PATCH
18692
    method as a means of describing a set of modifications to a target
18693
    resource's content. This function applies a merge patch to the current
18694
    JSON value.
18695
18696
    The function implements the following algorithm from Section 2 of
18697
    [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396):
18698
18699
    ```
18700
    define MergePatch(Target, Patch):
18701
      if Patch is an Object:
18702
        if Target is not an Object:
18703
          Target = {} // Ignore the contents and set it to an empty Object
18704
        for each Name/Value pair in Patch:
18705
          if Value is null:
18706
            if Name exists in Target:
18707
              remove the Name/Value pair from Target
18708
          else:
18709
            Target[Name] = MergePatch(Target[Name], Value)
18710
        return Target
18711
      else:
18712
        return Patch
18713
    ```
18714
18715
    Thereby, `Target` is the current object; that is, the patch is applied to
18716
    the current value.
18717
18718
    @param[in] patch  the patch to apply
18719
18720
    @complexity Linear in the lengths of @a patch.
18721
18722
    @liveexample{The following code shows how a JSON Merge Patch is applied to
18723
    a JSON document.,merge_patch}
18724
18725
    @sa @ref patch -- apply a JSON patch
18726
    @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396)
18727
18728
    @since version 3.0.0
18729
    */
18730
    void merge_patch(const basic_json& patch)
18731
    {
18732
        if (patch.is_object())
18733
        {
18734
            if (not is_object())
18735
            {
18736
                *this = object();
18737
            }
18738
            for (auto it = patch.begin(); it != patch.end(); ++it)
18739
            {
18740
                if (it.value().is_null())
18741
                {
18742
                    erase(it.key());
18743
                }
18744
                else
18745
                {
18746
                    operator[](it.key()).merge_patch(it.value());
18747
                }
18748
            }
18749
        }
18750
        else
18751
        {
18752
            *this = patch;
18753
        }
18754
    }
18755
18756
    /// @}
18757
};
18758
} // namespace nlohmann
18759
18760
///////////////////////
18761
// nonmember support //
18762
///////////////////////
18763
18764
// specialization of std::swap, and std::hash
18765
namespace std
18766
{
18767
18768
/// hash value for JSON objects
18769
template<>
18770
struct hash<nlohmann::json>
18771
{
18772
    /*!
18773
    @brief return a hash value for a JSON object
18774
18775
    @since version 1.0.0
18776
    */
18777
    std::size_t operator()(const nlohmann::json& j) const
0
18778
    {
0
18779
        // a naive hashing via the string representation
0
18780
        const auto& h = hash<nlohmann::json::string_t>();
0
18781
        return h(j.dump());
0
18782
    }
18783
};
18784
18785
/// specialization for std::less<value_t>
18786
/// @note: do not remove the space after '<',
18787
///        see https://github.com/nlohmann/json/pull/679
18788
template<>
18789
struct less< ::nlohmann::detail::value_t>
18790
{
18791
    /*!
18792
    @brief compare two value_t enum values
18793
    @since version 3.0.0
18794
    */
18795
    bool operator()(nlohmann::detail::value_t lhs,
18796
                    nlohmann::detail::value_t rhs) const noexcept
0
18797
    {
0
18798
        return nlohmann::detail::operator<(lhs, rhs);
0
18799
    }
18800
};
18801
18802
/*!
18803
@brief exchanges the values of two JSON objects
18804
18805
@since version 1.0.0
18806
*/
18807
template<>
18808
inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
18809
    is_nothrow_move_constructible<nlohmann::json>::value and
18810
    is_nothrow_move_assignable<nlohmann::json>::value
18811
)
0
18812
{
0
18813
    j1.swap(j2);
0
18814
}
18815
18816
} // namespace std
18817
18818
/*!
18819
@brief user-defined string literal for JSON values
18820
18821
This operator implements a user-defined string literal for JSON objects. It
18822
can be used by adding `"_json"` to a string literal and returns a JSON object
18823
if no parse error occurred.
18824
18825
@param[in] s  a string representation of a JSON object
18826
@param[in] n  the length of string @a s
18827
@return a JSON object
18828
18829
@since version 1.0.0
18830
*/
18831
inline nlohmann::json operator "" _json(const char* s, std::size_t n)
0
18832
{
0
18833
    return nlohmann::json::parse(s, s + n);
0
18834
}
18835
18836
/*!
18837
@brief user-defined string literal for JSON pointer
18838
18839
This operator implements a user-defined string literal for JSON Pointers. It
18840
can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer
18841
object if no parse error occurred.
18842
18843
@param[in] s  a string representation of a JSON Pointer
18844
@param[in] n  the length of string @a s
18845
@return a JSON pointer object
18846
18847
@since version 2.0.0
18848
*/
18849
inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
0
18850
{
0
18851
    return nlohmann::json::json_pointer(std::string(s, n));
0
18852
}
18853
18854
// #include <nlohmann/detail/macro_unscope.hpp>
18855
18856
18857
// restore GCC/clang diagnostic settings
18858
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
18859
    #pragma GCC diagnostic pop
18860
#endif
18861
#if defined(__clang__)
18862
    #pragma GCC diagnostic pop
18863
#endif
18864
18865
// clean up
18866
#undef JSON_INTERNAL_CATCH
18867
#undef JSON_CATCH
18868
#undef JSON_THROW
18869
#undef JSON_TRY
18870
#undef JSON_LIKELY
18871
#undef JSON_UNLIKELY
18872
#undef JSON_DEPRECATED
18873
#undef JSON_HAS_CPP_14
18874
#undef JSON_HAS_CPP_17
18875
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
18876
#undef NLOHMANN_BASIC_JSON_TPL
18877
18878
18879
#endif
/home/pi/programowanie/iDom_server_OOP/test/iDom_TESTs-CMAKE/../../test/iDom_TESTs-CMAKE/../../../iDom_server_OOP/src/iDomTools/test/../../RADIO_433_eq/../433MHz/RFLink/../../iDom_server_OOP.h
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
224
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
64
41
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
4.23k
164
    {
4.23k
165
4.23k
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    RADIO_EQ_CONTAINER *main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/home/pi/programowanie/iDom_server_OOP/test/iDom_TESTs-CMAKE/../../test/iDom_TESTs-CMAKE/../../../iDom_server_OOP/src/iDomTools/test/../../RADIO_433_eq/radio_433_eq.h
1
#ifndef RADIO_SWITCH_H
2
#define RADIO_SWITCH_H
3
#include <gtest/gtest.h>
4
#include <gmock/gmock.h>
5
#include <map>
6
#include "../iDomStatus/idomstatus.h"
7
#include "../433MHz/RFLink/rflinkhandler.h"
8
9
#include "../433MHz/rc_433mhz.h"
10
#include "json.hpp"
11
12
struct WEATHER_STRUCT{
13
private:
14
    unsigned long int m_counter = 0;
15
protected:
16
    unsigned int m_humidity = 0;
17
    double m_temperature = 0.0;
18
    unsigned int m_barometricPressure = 0;
19
public:
20
    unsigned int getHumidity(){ return m_humidity; }
21
    double getTemperature(){ return m_temperature; }
22
    unsigned int getBarometricPressure(){ return m_barometricPressure; }
23
    std::string getDataString(){
24
        return "data: "+std::to_string(m_counter)+"\n"+"Humidity=" + std::to_string(getHumidity()) +"%\n"+
25
                "temperature= " + to_string_with_precision(getTemperature()) + "c\n"+
26
                "Pressure= " + std::to_string(getBarometricPressure())+ "kPa\n";
27
    }
28
29
    void putData(std::string data){
30
        std::string tempStr;
31
        int t = 0;
32
        ++m_counter;
33
        try{
34
            m_humidity = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "HUM") );
35
        }
36
        catch (...){ }
37
        try{
38
            m_barometricPressure = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "BARO") );
39
        }
40
        catch (...){ }
41
        try{
42
            tempStr = RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "TEMP");
43
            std::stringstream ss;
44
            ss << std::hex << tempStr.substr(tempStr.size()-3,tempStr.size());
45
            ss >> t;
46
            m_temperature = t / 10.0;
47
            if(tempStr.at(0) == '8'){
48
                m_temperature *= -1.0;
49
            }
50
        }
51
        catch (...){ }
52
        //std::cout << "DUPA: "<<data<<" temp=" << m_temperature<< " hum="<<m_humidity<< std::endl;
53
    }
54
};
55
56
enum class RADIO_EQ_TYPE{
57
    SWITCH = 1,
58
    PIR,
59
    GATE,
60
    BUTTON,
61
    WEATHER_S,
62
    NONE
63
};
64
struct RADIO_EQ_CONFIG{
65
    std::string name = "NULL";
66
    std::string ID   = "NULL";
67
    std::string type = "NULL";
68
    std::string onCode  = "NULL";
69
    std::string offCode = "NULL";
70
    std::string on15sec = "NULL";
71
    std::string sunrise = "NULL";
72
    std::string sunset  = "NULL";
73
    std::string lock   = "NULL";
74
    std::string unlock = "NULL";
75
    void set(std::string type,
76
             std::string name,
77
             std::string ID,
78
             std::string onCode = "null",
79
             std::string offCode = "null",
80
             std::string on15sec = "null",
81
             std::string sunrise = "null",
82
             std::string sunset = "null",
83
             std::string lock = "null",
84
             std::string unlock = "null"){
85
        this->name = name;
86
        this->ID   = ID;
87
        this->type = type;
88
        this->onCode  = onCode;
89
        this->offCode = offCode;
90
        this->on15sec = on15sec;
91
        this->sunrise = sunrise;
92
        this->sunset  = sunset;
93
        this->lock   = lock;
94
        this->unlock = unlock;
95
    }
96
97
    nlohmann::json getJson(){
98
        nlohmann::json jj;
99
        jj["name"]  = name;
100
        jj["id"]    = ID;
101
        jj["type"]  = type;
102
        jj["ON"]    = onCode;
103
        jj["OFF"]   = offCode;
104
        jj["on15sec"] = on15sec;
105
        jj["sunrise"] = sunrise;
106
        jj["sunset"]  = sunset;
107
        jj["lock"]   = lock;
108
        jj["unlock"] = unlock;
109
        return jj;
110
    }
111
};
112
113
class RADIO_EQ{
114
public:
115
    RADIO_EQ();
116
    virtual ~RADIO_EQ();
117
    virtual STATE getState() = 0;
118
    virtual std::string getName() = 0;
119
    virtual std::string getID() = 0;
120
    virtual RADIO_EQ_TYPE getType();
121
protected:
122
    thread_data *m_my_data;
123
    RADIO_EQ_TYPE m_type;
124
public:
125
    RADIO_EQ_CONFIG m_config;
126
};
127
class RADIO_WEATHER_STATION: public RADIO_EQ
128
{
129
    STATE m_state = STATE::UNDEFINE;
130
131
public:
132
    RADIO_WEATHER_STATION(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
133
    ~RADIO_WEATHER_STATION();
134
    STATE getState();
135
    std::string getName();
136
    std::string getID();
137
    // data
138
    WEATHER_STRUCT data;
139
};
140
class RADIO_BUTTON: public RADIO_EQ
141
{
142
    STATE m_state = STATE::UNDEFINE;
143
144
public:
145
    RADIO_BUTTON(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
146
    ~RADIO_BUTTON();
147
    STATE getState();
148
    void setState(STATE s);
149
    std::string getName();
150
    std::string getID();
151
};
152
153
class RADIO_SWITCH: public RADIO_EQ
154
{
155
#ifdef BT_TEST
156
public:
157
#endif
158
    RC_433MHz main433MHz;
159
    STATE m_state = STATE::UNDEFINE;
160
public:
161
    RADIO_SWITCH(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
162
    ~RADIO_SWITCH();
163
    void on();
164
    void off();
165
    void onFor15sec();
166
    void onSunrise();
167
    void onSunset();
168
    void onLockHome();
169
    void onUnlockHome();
170
    STATE getState();
171
    std::string getName();
172
    std::string getID();
173
    void setCode(RADIO_EQ_CONFIG cfg);
174
    STATE m_sunrise = STATE::UNDEFINE;
175
    STATE m_sunset  = STATE::UNDEFINE;
176
};
177
178
class RADIO_EQ_CONTAINER
179
{
180
    std::map <std::string, RADIO_EQ* > m_radioEqMap;
181
    thread_data * my_data;
182
    nlohmann::json m_configJson;
183
public:
184
    RADIO_EQ_CONTAINER(thread_data * my_data);
185
    virtual ~RADIO_EQ_CONTAINER();
186
    void addRadioEq(RADIO_EQ_CONFIG cfg, RADIO_EQ_TYPE type);
187
    void addRadioEq(RADIO_EQ_CONFIG cfg, const std::string& type);
188
    void deleteRadioEq(const std::string &name);
189
    virtual RADIO_EQ* getEqPointer(std::string name);
190
    std::vector<RADIO_SWITCH*> getSwitchPointerVector();
191
    std::vector<RADIO_BUTTON*> getButtonPointerVector();
192
    std::vector<RADIO_WEATHER_STATION *> getWeather_StationPtrVector();
193
    std::string listAllName();
194
    bool nameExist(const std::string &name);
195
    void loadConfig(const std::string &filePath);
196
    void saveConfig(const std::string &filePath);
197
};
198
199
class RADIO_EQ_CONTAINER_STUB : public RADIO_EQ_CONTAINER
200
{
201
    thread_data * k;
202
public:
0
203
    RADIO_EQ_CONTAINER_STUB(thread_data * k):RADIO_EQ_CONTAINER(k){this->k = k;}
204
0
205
    virtual ~RADIO_EQ_CONTAINER_STUB(){puts("~RADIO_EQ_CONTAINER_STUB()");}
206
    MOCK_METHOD1(getEqPointer, RADIO_EQ*(std::string name));
207
};
208
209
#endif // RADIO_SWITCH_H
/home/pi/programowanie/iDom_server_OOP/test/iDom_TESTs-CMAKE/../../test/iDom_TESTs-CMAKE/../../../iDom_server_OOP/src/iDomTools/test/../lightning.h
1
#ifndef LIGHTNING_H
2
#define LIGHTNING_H
3
#include <iostream>
4
5
#include "../../libs/Statistic/statistic.h"
6
#include "../../libs/useful/useful.h"
7
8
#include "idomtools_useful.h"
9
#include "json.hpp"
10
11
class CARDINAL_DIRECTIONS{
12
public:
13
    enum class CARDINAL_DIRECTIONS_ENUM{
14
        /*
15
           N
16
        NNW NNE
17
      NW       NE
18
   WNW		     ENE
19
 W				    E
20
   WSW			 ESE
21
      SW	   SE
22
        SSW	 SSE
23
           S
24
    */
25
26
        N = 1,NNE,NE,ENE,E,ESE,SE,SSE,S,SSW,SW,WSW,W,WNW,NW,NNW,ERROR
27
    };
28
    static CARDINAL_DIRECTIONS_ENUM stringToCardinalDirectionsEnum(std::string s){
29
        if (s == "N")      return CARDINAL_DIRECTIONS_ENUM::N;
30
        else if (s == "NNE")    return CARDINAL_DIRECTIONS_ENUM::NNE;
31
        else if (s == "NE")     return CARDINAL_DIRECTIONS_ENUM::NE;
32
        else if (s == "ENE")    return CARDINAL_DIRECTIONS_ENUM::ENE;
33
        else if (s == "E")      return CARDINAL_DIRECTIONS_ENUM::E;
34
        else if (s == "ESE")    return CARDINAL_DIRECTIONS_ENUM::ESE;
35
        else if (s == "SE")     return CARDINAL_DIRECTIONS_ENUM::SE;
36
        else if (s == "SSE")    return CARDINAL_DIRECTIONS_ENUM::SSE;
37
        else if (s == "S")      return CARDINAL_DIRECTIONS_ENUM::S;
38
        else if (s == "SSW")    return CARDINAL_DIRECTIONS_ENUM::SSW;
39
        else if (s == "SW")     return CARDINAL_DIRECTIONS_ENUM::SW;
40
        else if (s == "WSW")    return CARDINAL_DIRECTIONS_ENUM::WSW;
41
        else if (s == "W")      return CARDINAL_DIRECTIONS_ENUM::W;
42
        else if (s == "WNW")    return CARDINAL_DIRECTIONS_ENUM::WNW;
43
        else if (s == "NW")     return CARDINAL_DIRECTIONS_ENUM::NW;
44
        else if (s == "NNW")    return CARDINAL_DIRECTIONS_ENUM::NNW;
45
        else                    return CARDINAL_DIRECTIONS_ENUM::ERROR;
46
    }
47
48
    static std::string cardinalDirectionsEnumToString(CARDINAL_DIRECTIONS_ENUM e){
49
        switch (e){
50
        case CARDINAL_DIRECTIONS_ENUM::N:
51
            return "N";
52
        case CARDINAL_DIRECTIONS_ENUM::NNE:
53
            return "NNE";
54
        case CARDINAL_DIRECTIONS_ENUM:: NE:
55
            return "NE";
56
        case CARDINAL_DIRECTIONS_ENUM::ENE:
57
            return "ENE";
58
        case CARDINAL_DIRECTIONS_ENUM::E:
59
            return "E";
60
        case CARDINAL_DIRECTIONS_ENUM::ESE:
61
            return "ESE";
62
        case CARDINAL_DIRECTIONS_ENUM::SE:
63
            return "SE";
64
        case CARDINAL_DIRECTIONS_ENUM::SSE:
65
            return "SSE";
66
        case CARDINAL_DIRECTIONS_ENUM::S:
67
            return "S";
68
        case CARDINAL_DIRECTIONS_ENUM::SSW:
69
            return "SSW";
70
        case CARDINAL_DIRECTIONS_ENUM::SW:
71
            return "SW";
72
        case CARDINAL_DIRECTIONS_ENUM::WSW:
73
            return "WSW";
74
        case CARDINAL_DIRECTIONS_ENUM::W:
75
            return "W";
76
        case CARDINAL_DIRECTIONS_ENUM::WNW:
77
            return "WNW";
78
        case CARDINAL_DIRECTIONS_ENUM::NW:
79
            return "NW";
80
        case CARDINAL_DIRECTIONS_ENUM::NNW:
81
            return "NNW";
82
        default:
83
            return "UNKNOWN DIRECTION";
84
        }
85
    }
86
    static std::string cardinalDirectionsEnumToHuman(CARDINAL_DIRECTIONS_ENUM e){
87
        switch (e){
88
        case CARDINAL_DIRECTIONS_ENUM::N:
89
            return "północ";
90
        case CARDINAL_DIRECTIONS_ENUM::NNE:
91
            return "północ - północny wschód";
92
        case CARDINAL_DIRECTIONS_ENUM:: NE:
93
            return "północny wschód";
94
        case CARDINAL_DIRECTIONS_ENUM::ENE:
95
            return "wschód - północny wschód";
96
        case CARDINAL_DIRECTIONS_ENUM::E:
97
            return "wschód";
98
        case CARDINAL_DIRECTIONS_ENUM::ESE:
99
            return "wschód - południowy wschód";
100
        case CARDINAL_DIRECTIONS_ENUM::SE:
101
            return "południowy wschód";
102
        case CARDINAL_DIRECTIONS_ENUM::SSE:
103
            return "południe - południowy wschód";
104
        case CARDINAL_DIRECTIONS_ENUM::S:
105
            return "południe";
106
        case CARDINAL_DIRECTIONS_ENUM::SSW:
107
            return "południe - południowy zachów";
108
        case CARDINAL_DIRECTIONS_ENUM::SW:
109
            return "południowy zachów";
110
        case CARDINAL_DIRECTIONS_ENUM::WSW:
111
            return "zachód - południowy zachów";
112
        case CARDINAL_DIRECTIONS_ENUM::W:
113
            return "zachód";
114
        case CARDINAL_DIRECTIONS_ENUM::WNW:
115
            return "zachód - północny zachód";
116
        case CARDINAL_DIRECTIONS_ENUM::NW:
117
            return "północny zachód";
118
        case CARDINAL_DIRECTIONS_ENUM::NNW:
119
            return "północ - północny zachód";
120
        default:
121
            return "UNKNOWN DIRECTION";
122
        }
123
    }
124
    struct ALARM_INFO{
125
        ALARM_INFO():
126
            riseAlarm(false),
127
            timestamp(0),
128
            distance(0.0),
129
            bearingENG(CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ERROR)
1.12k
130
        {
1.12k
131
            data << "NULL";
1.12k
132
        }
133
        ALARM_INFO(const ALARM_INFO &s):
134
            riseAlarm(s.riseAlarm),
135
            data(s.data.str()),
136
            timestamp(s.timestamp),
137
            distance(s.distance),
138
            bearingENG(s.bearingENG)
139
        {
140
        }
141
        ALARM_INFO& operator = (const ALARM_INFO& s)
142
        {
143
            this->data.str(std::string());
144
            this->riseAlarm = s.riseAlarm;
145
            this->data << s.data.str();
146
            this->timestamp = s.timestamp;
147
            this->distance = s.distance;
148
            this->bearingENG = s.bearingENG;
149
            return *this;
150
        }
151
152
        bool riseAlarm;
153
        std::stringstream data;
154
        unsigned int timestamp; //second
155
        double distance; //km
156
        CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM bearingENG;
157
    };
158
};
159
160
class LIGHTNING
161
{
162
public:
163
    LIGHTNING();
164
    ~LIGHTNING();
165
    CARDINAL_DIRECTIONS::ALARM_INFO lightningAlert(nlohmann::json jj);
166
    bool checkLightningAlert(CARDINAL_DIRECTIONS::ALARM_INFO* info);
167
private:
168
    bool alarmState = false;
169
    Clock lightningTime;
170
    double oldDistance = 0.0;
171
};
172
173
#endif // LIGHTNING_H
/home/pi/programowanie/iDom_server_OOP/test/iDom_TESTs-CMAKE/../../test/iDom_TESTs-CMAKE/../../../iDom_server_OOP/src/iDomTools/test/iDomTools_fixture.h
1
#include <gtest/gtest.h>
2
#include "test_data.h"
3
#include "../idomtools.h"
4
#include "../../src/functions/functions.h"
5
#include "../../RADIO_433_eq/radio_433_eq.h"
6
#include "testJSON.h"
7
8
class iDomTOOLS_ClassTest : public ::testing::Test
9
{
10
public:
11
    TEST_JSON test_Json;
12
    LIGHTNING test_lightning;
13
    CARDINAL_DIRECTIONS::ALARM_INFO test_struct;
14
    thread_data test_my_data;
15
    iDomSTATUS test_status;
16
    config test_server_set;
17
    RADIO_EQ_CONTAINER test_rec;
18
    iDOM_STATE main_iDomStatus;
19
    ALERT test_alarmTime;
20
    pilot_led test_pilot_led;
21
    MPD_info test_ptr_MPD;
22
23
    /// pointer
24
    iDomTOOLS* test_idomTOOLS;
25
    /////// method
26
    iDomTOOLS_ClassTest():test_rec(&test_my_data)
524
27
    {
524
28
        std::cout << "konstruktor testu " <<std::endl;
524
29
    }
30
    void SetUp()
520
31
    {
520
32
        std::cout << "SetUP testu iDomTOOLS_ClassTest" <<std::endl;
520
33
        test_server_set.TS_KEY = "key test";
520
34
        test_server_set.viberSender = "test sender";
520
35
        test_server_set.viberReceiver = {"R1","R2"};
520
36
        test_server_set.saveFilePath = "/mnt/ramdisk/iDomStateTest2.save";
520
37
        test_server_set.radio433MHzConfigFile = "/mnt/ramdisk/433_eq_conf.json";
520
38
        test_rec.loadConfig(test_server_set.radio433MHzConfigFile);
520
39
520
40
        test_my_data.main_REC = (&test_rec);
520
41
        test_my_data.server_settings = &test_server_set;
520
42
        test_my_data.main_iDomStatus = &test_status;
520
43
        test_my_data.alarmTime = test_alarmTime;
520
44
        test_my_data.idom_all_state = main_iDomStatus;
520
45
        test_my_data.ptr_pilot_led = &test_pilot_led;
520
46
520
47
        test_status.addObject("house");
520
48
520
49
        /////////// create
520
50
        test_idomTOOLS = new iDomTOOLS(&test_my_data);
520
51
520
52
        test_my_data.main_iDomTools = test_idomTOOLS;
520
53
        test_ptr_MPD.volume = 3;
520
54
        test_my_data.ptr_MPD_info = &test_ptr_MPD;
520
55
520
56
        useful_F::myStaticData = &test_my_data;
520
57
    }
58
59
    void TearDown()
520
60
    {
520
61
        delete test_idomTOOLS;
520
62
    }
63
};
64
/home/pi/programowanie/iDom_server_OOP/test/iDom_TESTs-CMAKE/../../test/iDom_TESTs-CMAKE/../../src/functions/../blockQueue/../logger/logger.hpp
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
0
84
    {
0
85
        *static_cast<std::ostringstream *>(this) << t;
0
86
        return (*this);
0
87
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/home/pi/programowanie/iDom_server_OOP/test/iDom_TESTs-CMAKE/../../test/iDom_TESTs-CMAKE/../../src/functions/../c_connection/../iDom_server_OOP.h
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
0
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
0
41
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    RADIO_EQ_CONTAINER *main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/home/pi/programowanie/iDom_server_OOP/test/iDom_TESTs-CMAKE/main.cpp
1
#include <iostream>
2
#include <gtest/gtest.h>
3
#include <gmock/gmock.h>
4
#include <gconv.h>
5
#include <fstream>
6
#include <sstream>
7
#include <test_data.h>
8
#include <../../../../libs/useful/useful.h>
9
#include "../../../../src/SerialPi/serialpi.h"
10
#include "../../../../src/functions/functions.h"
11
10
12
#define log_file_cout f_log //std::cout   zmien f_log na std::cout  i bedzie wypisywac na
13
std::string  _logfile = "/mnt/ramdisk/iDom_log_BT.log";
14
15
Logger log_file_mutex(_logfile);
16
17
18
std::string TEST_DATA::return_send_to_arduino = "-2:-2";
19
std::string TEST_DATA::return_httpPost = "ok.\n";
20
std::string TEST_DATA::return_httpPost_expect = "";
21
std::string TEST_DATA::return_viber_msg = "";
22
std::string TEST_DATA::serial_b = "NULL";
23
std::string TEST_DATA::serial_sended = "NULL";
24
std::string TEST_DATA::LCD_print = "NULL";
25
int TEST_DATA::test_pin = 0;
26
27
unsigned int Clock::m_BT_H = 0;
28
unsigned int Clock::m_BT_M = 0;
29
28
30
void SerialPi_set_recv_msg(const std::string& m){
28
31
    TEST_DATA::serial_b = m;
28
32
}
33
40
34
void SerialPi_set_serial_sended(const std::string& m){
40
35
    TEST_DATA::serial_sended = m;
40
36
}
228
37
SerialPi::SerialPi(const std::string& a):m_serial_port(10){
228
38
    std::cout << "SerialPi() addres: " << a << std::endl;
228
39
}
228
40
SerialPi::~SerialPi(){
228
41
    std::cout << "~SerialPi()" << std::endl;
228
42
}
43
40
44
void SerialPi::print(const std::string& msg){
40
45
    std::cout << "SerialPi::print() msg: " << msg << std::endl;
40
46
    SerialPi_set_serial_sended(msg);
40
47
}
48
49
36
50
void SerialPi::begin(int serialSpeed){
36
51
    std::cout << "SerialPi::int() serialSpeed: " << serialSpeed << std::endl;
36
52
}
53
12
54
void SerialPi::flush(){
12
55
    std::cout << "SerialPi::flush()" << std::endl;
12
56
    TEST_DATA::serial_b.clear();
12
57
}
58
60
59
int SerialPi::available(){
60
60
    std::cout << "SerialPi::available() " << TEST_DATA::serial_b.size() << std::endl;
60
61
    return static_cast<int>(TEST_DATA::serial_b.size());
60
62
}
63
156
64
char SerialPi::read(){
156
65
    char r = TEST_DATA::serial_b.at(0);
156
66
    TEST_DATA::serial_b.erase(0,1);
156
67
    std::cout << "SerialPi::read(): "<<r<< std::endl;
156
68
    return r;
156
69
}
70
71
bool useful_F::go_while = true;
72
bool useful_F::workServer = true;
73
0
74
void useful_F::button_interrupt(){}
80
75
void digitalWrite(int pin, int mode){}
76
77
void setReturnPinState(int i)
28
78
{
28
79
    TEST_DATA::test_pin = i;
28
80
}
81
176
82
std::string useful_F::send_to_arduino(thread_data *my_data, const std::string& d){
176
83
    puts("useful_F::send_to_arduino()");
176
84
    return TEST_DATA::return_send_to_arduino;
176
85
}
520
86
viber_API::viber_API(){}
520
87
void viber_API::setAccessToken(const std::string& accessToken){}
520
88
void viber_API::setURL(const std::string& url){}
528
89
void viber_API::setAvatar (const std::string& avatar){}
90
std::string viber_API::sendViberMSG(const std::string& msg,
91
                                    const std::string& receiver,
92
                                    const std::string& senderName,
93
                                    const std::string& accessToken,
44
94
                                    const std::string& url){
44
95
44
96
    std::cout << "sendViberMSG() "<< msg <<" to: "<< receiver << std::endl;
44
97
    TEST_DATA::return_viber_msg = msg;
44
98
    return"{\"message_status\":\"ok\"}";
44
99
}
100
std::string viber_API::sendViberPicture(const std::string& msg,
101
                                        const std::string& image,
102
                                        const std::string& receiver,
103
                                        const std::string& senderName,
104
                                        const std::string& accessToken ,
100
105
                                        const std::string& url){
100
106
    std::cout << "sendViberPicture() "<< msg <<" to: "<< receiver << std::endl;
100
107
    TEST_DATA::return_viber_msg = msg;
100
108
    return"{\"message_status\":\"ok\"}";
100
109
}
520
110
FACEBOOK_API::FACEBOOK_API(){}
111
std::string FACEBOOK_API::postTxtOnWall(const std::string& msg,
0
112
                                        const std::string& accessToken ){return "";}
113
std::string FACEBOOK_API::postPhotoOnWall(const std::string& url,
114
                                          const std::string& msg ,
8
115
                                          const std::string& accessToken ){return "";}
520
116
void FACEBOOK_API::setAccessToken(const std::string& token){}
117
136
118
void LCD_c::set_lcd_STATE(int i){}
696
119
void LCD_c::printString(bool clear, int col, int row, const std::string& str){
696
120
    std::cout << "LCD_c::printString() "<< str << std::endl;
696
121
    TEST_DATA::LCD_print = str;
696
122
}
123
56
124
std::string useful_F_libs::httpPost(const std::string& url, int timeoutSeconds){
56
125
56
126
    std::cout << "url: "<< url << " return "<< TEST_DATA::return_httpPost << "|"<< std::endl;
56
127
    TEST_DATA::return_httpPost_expect = "httpPost";
56
128
    return TEST_DATA::return_httpPost;
56
129
}
16
130
std::string useful_F_libs::httpPost(const std::string& url){
16
131
    CURL *curl;
16
132
    CURLcode res;
16
133
    std::string readBuffer;
16
134
    curl = curl_easy_init();
16
135
16
136
    if(curl) {
16
137
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
16
138
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
16
139
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, useful_F_libs::WriteCallback);
16
140
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
16
141
        res = curl_easy_perform(curl);
16
142
        /* Check for errors */
16
143
        if(res != CURLE_OK)
0
144
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
0
145
                    curl_easy_strerror(res));
16
146
16
147
        /* always cleanup */
16
148
        curl_easy_cleanup(curl);
16
149
    }
16
150
    curl_global_cleanup();
16
151
16
152
    return readBuffer;
16
153
}
154
28
155
int digitalRead(int pin){ return TEST_DATA::test_pin; }
156
157
class test_433
158
{
159
public:
160
    std::string config433 = "{ \"BUTTON\": { \"locker\": { \"OFF\": \"NULL\", \"ON\": \"NULL\", \"id\": \"01e7be\", \"name\": \"locker\", \"type\": \"BUTTON\" } }, \"SWITCH\": { \"A\": { \"OFF\": \"10;TriState;0280aa;0;OFF\", \"ON\": \"10;TriState;0280aa;0;ON\", \"id\": \"1444\", \"name\": \"A\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"null\", \"unlock\": \"null\", \"type\": \"SWITCH\" }, \"ALARM\": { \"OFF\": \"dummyOFF\", \"ON\": \"dummyON\", \"id\": \"1223\", \"name\": \"ALARM\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"null\", \"unlock\": \"null\", \"type\": \"SWITCH\" }, \"B\": { \"OFF\": \"10;TriState;02822a;0;OFF\", \"ON\": \"10;TriState;02822a;0;ON\", \"id\": \"1445\", \"name\": \"B\", \"on15sec\": \"null\", \"sunrise\": \"ON\", \"sunset\": \"OFF\", \"lock\": \"null\", \"unlock\": \"null\",\"type\": \"SWITCH\" }, \"C\": { \"OFF\": \"10;TriState;02828a;0;OFF\", \"ON\": \"10;TriState;02828a;0;ON\", \"id\": \"1446\", \"name\": \"C\", \"on15sec\": \"null\", \"sunrise\": \"OFF\", \"sunset\": \"ON\", \"lock\": \"null\", \"unlock\": \"null\",\"type\": \"SWITCH\" }, \"listwa\": { \"OFF\": \"10;Kaku;0ad04d;15;OFF\", \"ON\": \"10;Kaku;0ad04d;15;ON\", \"id\": \"1450\", \"name\": \"listwa\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"OFF\", \"unlock\": \"ON\", \"type\": \"SWITCH\" } }, \"WEATHER\": { \"first\": { \"OFF\": \"NULL\", \"ON\": \"NULL\", \"id\": \"0704\", \"name\": \"first\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\", \"type\": \"WEATHER\" } } }";
161
    std::string config433_fake = "{ \"BUTTON\": { \"locker\": { \"OFF\": \"NULL\", \"ON\": \"NULL\", \"id\": \"01e7be\", \"name\": \"locker\",  \"type\": \"BUTTON\" } }, \"SWITCH\": { \"A\": { \"OFF\": \"10;TriState;0280aa;0;OFF\", \"ON\": \"10;TriState;0280aa;0;ON\", \"id\": \"1444\", \"name\": \"A\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"null\", \"unlock\": \"null\", \"type\": \"SWITCH\" }, \"ALARM\": { \"OFF\": \"dummyOFF\", \"ON\": \"dummyON\", \"id\": \"1223\", \"name\": \"ALARM\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"null\", \"unlock\": \"null\", \"type\": \"SWITCH\" }, \"B\": { \"OFF\": \"10;TriState;02822a;0;OFF\", \"ON\": \"10;TriState;02822a;0;ON\", \"id\": \"1445\", \"name\": \"B\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\", \"lock\": \"null\", \"unlock\": \"null\",\"type\": \"SWITCH\" }, \"C\": { \"OFF\": \"10;TriState;02828a;0;OFF\", \"ON\": \"10;TriState;02828a;0;ON\", \"id\": \"1446\", \"name\": \"C\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"null\", \"unlock\": \"null\", \"type\": \"SWITCH\" }, \"listwa\": { \"OFF\": \"10;Kaku;0ad04d;15;OFF\", \"ON\": \"10;Kaku;0ad04d;15;ON\", \"id\": \"1450\", \"name\": \"listwa\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"OFF\", \"unlock\": \"null\", \"type\": \"SWITCH\" } } } }";
162
163
    void makeFile(const std::string& path)
1
164
    {
1
165
        std::ofstream o(path);
1
166
        o << config433 ;
1
167
    }
168
    void makeFileFake(const std::string& path)
1
169
    {
1
170
        std::ofstream o(path);
1
171
        o << config433_fake ;
1
172
    }
173
};
174
175
int main(int argc, char **argv)
1
176
{
1
177
    test_433 t;
1
178
    t.makeFile("/mnt/ramdisk/433_eq_conf.json");
1
179
    t.makeFileFake("/mnt/ramdisk/433_eq_conf_fake.json");
1
180
1
181
    std::fstream ofs;
1
182
    ofs.open(_logfile, std::ios::out | std::ios::trunc);
1
183
    ofs.close(); //Using microsoft incremental linker version 14
1
184
1
185
    pthread_mutex_init(&Logger::mutex_log, NULL);
1
186
1
187
    log_file_mutex.mutex_lock();
1
188
    log_file_cout << std::endl<< std::endl<<"============================================"
1
189
                  << std::endl<< std::endl<< std::endl<< INFO << "START BT "<< std::endl;
1
190
    log_file_mutex.mutex_unlock();
1
191
1
192
    ::testing::InitGoogleTest( &argc, argv );
1
193
    //::testing::GTEST_FLAG(filter) = "functions_fixture.sleepThread";
1
194
    //::testing::GTEST_FLAG(filter) = "event_counter_fixture.getLast1minNumberEvent";
1
195
    //::testing::GTEST_FLAG(filter) = "command433MHz_Class_fixture.*)";
1
196
    auto ret = RUN_ALL_TESTS();
1
197
    pthread_mutex_destroy(&Logger::mutex_log);
1
198
1
199
    const char * PROG_INFO =  " Basic TEST iDomServer: " __DATE__ ", " __TIME__;
1
200
    std::cout << "wersja " <<PROG_INFO <<" "<< GIT_BRANCH <<" " << GIT_COMMIT_HASH << std::endl;
1
201
    return ret;
1
202
}